Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6: (67 commits) ide: remove redundant DMA blacklist check from __ide_dma_on() ide: cleanup ide_set_dma() ide: remove redundant ->ide_dma_on call from set_using_dma() sc1200: move DMA timings to timing tables ide: add IDE_HFLAG_ABUSE_SET_DMA_MODE host flag sis5513: factor out UDMA programming code pdc202xx_new: move PIO programming code to pdcnew_set_pio_mode() ide: make 'extra' field in struct ide_port_info u8 ide: kill duplicate code in ide_dump_{ata,atapi}_status() ide-disk: use ide_get_lba_addr() ide: printk fix ide: add ide_tf_read() helper ide: fix registers loading order in ide_dump_ata_status() ide-disk: use do_rw_taskfile() (take 2) ide-disk: add ide_tf_set_cmd() helper ide-disk: extend timeout for PIO-in commands ide: remove 'handler' field from ide_task_t (take 2) ide: use ->data_phase to set ->handler in do_rw_taskfile() ide: convert do_rw_taskfile() to use ->data_phase ide: merge flagged_taskfile() into do_rw_taskfile() ...
This commit is contained in:
Коммит
f31c338675
|
@ -374,17 +374,6 @@ comment "PCI IDE chipsets support"
|
|||
config BLK_DEV_IDEPCI
|
||||
bool
|
||||
|
||||
config IDEPCI_SHARE_IRQ
|
||||
bool "Sharing PCI IDE interrupts support"
|
||||
depends on BLK_DEV_IDEPCI
|
||||
help
|
||||
Some ATA/IDE chipsets have hardware support which allows for
|
||||
sharing a single IRQ with other cards. To enable support for
|
||||
this in the ATA/IDE driver, say Y here.
|
||||
|
||||
It is safe to say Y to this question, in most cases.
|
||||
If unsure, say N.
|
||||
|
||||
config IDEPCI_PCIBUS_ORDER
|
||||
def_bool BLK_DEV_IDE=y && BLK_DEV_IDEPCI
|
||||
|
||||
|
@ -707,7 +696,6 @@ config BLK_DEV_SVWKS
|
|||
config BLK_DEV_SGIIOC4
|
||||
tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support"
|
||||
depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4
|
||||
select IDEPCI_SHARE_IRQ
|
||||
select BLK_DEV_IDEDMA_PCI
|
||||
help
|
||||
This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
|
||||
|
|
|
@ -272,8 +272,6 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
|
|||
case XFER_SW_DMA_0:
|
||||
cycle_time = 480;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -747,8 +747,6 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
strobe = ATA_DMA2_STROBE;
|
||||
hold = ATA_DMA2_HOLD;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (speed >= XFER_UDMA_0)
|
||||
|
|
|
@ -383,27 +383,19 @@ static int taskfile_load_raw(ide_drive_t *drive,
|
|||
gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
|
||||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args.data_phase = TASKFILE_NO_DATA;
|
||||
args.handler = &task_no_data_intr;
|
||||
|
||||
/* convert gtf to IDE Taskfile */
|
||||
args.tfRegister[1] = gtf->tfa[0]; /* 0x1f1 */
|
||||
args.tfRegister[2] = gtf->tfa[1]; /* 0x1f2 */
|
||||
args.tfRegister[3] = gtf->tfa[2]; /* 0x1f3 */
|
||||
args.tfRegister[4] = gtf->tfa[3]; /* 0x1f4 */
|
||||
args.tfRegister[5] = gtf->tfa[4]; /* 0x1f5 */
|
||||
args.tfRegister[6] = gtf->tfa[5]; /* 0x1f6 */
|
||||
args.tfRegister[7] = gtf->tfa[6]; /* 0x1f7 */
|
||||
memcpy(&args.tf_array[7], >f->tfa, 7);
|
||||
args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
|
||||
if (ide_noacpitfs) {
|
||||
DEBPRINT("_GTF execution disabled\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = ide_raw_taskfile(drive, &args, NULL);
|
||||
err = ide_no_data_taskfile(drive, &args);
|
||||
if (err)
|
||||
printk(KERN_ERR "%s: ide_raw_taskfile failed: %u\n",
|
||||
printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n",
|
||||
__FUNCTION__, err);
|
||||
|
||||
return err;
|
||||
|
|
|
@ -917,19 +917,13 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
|
|||
if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
|
||||
return startstop;
|
||||
|
||||
/* FIXME: for Virtual DMA we must check harder */
|
||||
if (info->dma)
|
||||
info->dma = !hwif->dma_setup(drive);
|
||||
|
||||
/* Set up the controller registers. */
|
||||
/* FIXME: for Virtual DMA we must check harder */
|
||||
HWIF(drive)->OUTB(info->dma, IDE_FEATURE_REG);
|
||||
HWIF(drive)->OUTB(0, IDE_IREASON_REG);
|
||||
HWIF(drive)->OUTB(0, IDE_SECTOR_REG);
|
||||
|
||||
HWIF(drive)->OUTB(xferlen & 0xff, IDE_BCOUNTL_REG);
|
||||
HWIF(drive)->OUTB(xferlen >> 8 , IDE_BCOUNTH_REG);
|
||||
if (IDE_CONTROL_REG)
|
||||
HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
|
||||
ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
|
||||
IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
|
||||
|
||||
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
|
||||
/* waiting for CDB interrupt, not DMA yet. */
|
||||
|
|
|
@ -129,6 +129,50 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
|
|||
return 0; /* lba_capacity value may be bad */
|
||||
}
|
||||
|
||||
static const u8 ide_rw_cmds[] = {
|
||||
WIN_MULTREAD,
|
||||
WIN_MULTWRITE,
|
||||
WIN_MULTREAD_EXT,
|
||||
WIN_MULTWRITE_EXT,
|
||||
WIN_READ,
|
||||
WIN_WRITE,
|
||||
WIN_READ_EXT,
|
||||
WIN_WRITE_EXT,
|
||||
WIN_READDMA,
|
||||
WIN_WRITEDMA,
|
||||
WIN_READDMA_EXT,
|
||||
WIN_WRITEDMA_EXT,
|
||||
};
|
||||
|
||||
static const u8 ide_data_phases[] = {
|
||||
TASKFILE_MULTI_IN,
|
||||
TASKFILE_MULTI_OUT,
|
||||
TASKFILE_IN,
|
||||
TASKFILE_OUT,
|
||||
TASKFILE_IN_DMA,
|
||||
TASKFILE_OUT_DMA,
|
||||
};
|
||||
|
||||
static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
|
||||
{
|
||||
u8 index, lba48, write;
|
||||
|
||||
lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
|
||||
write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
|
||||
|
||||
if (dma)
|
||||
index = drive->vdma ? 4 : 8;
|
||||
else
|
||||
index = drive->mult_count ? 0 : 4;
|
||||
|
||||
task->tf.command = ide_rw_cmds[index + lba48 + write];
|
||||
|
||||
if (dma)
|
||||
index = 8; /* fixup index */
|
||||
|
||||
task->data_phase = ide_data_phases[index / 2 + write];
|
||||
}
|
||||
|
||||
/*
|
||||
* __ide_do_rw_disk() issues READ and WRITE commands to a disk,
|
||||
* using LBA if supported, or CHS otherwise, to address sectors.
|
||||
|
@ -137,11 +181,11 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
|
|||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
unsigned int dma = drive->using_dma;
|
||||
u16 nsectors = (u16)rq->nr_sectors;
|
||||
u8 lba48 = (drive->addressing == 1) ? 1 : 0;
|
||||
task_ioreg_t command = WIN_NOP;
|
||||
ata_nsector_t nsectors;
|
||||
|
||||
nsectors.all = (u16) rq->nr_sectors;
|
||||
ide_task_t task;
|
||||
struct ide_taskfile *tf = &task.tf;
|
||||
ide_startstop_t rc;
|
||||
|
||||
if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
|
||||
if (block + rq->nr_sectors > 1ULL << 28)
|
||||
|
@ -155,121 +199,76 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
|
|||
ide_map_sg(drive, rq);
|
||||
}
|
||||
|
||||
if (IDE_CONTROL_REG)
|
||||
hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
|
||||
|
||||
/* FIXME: SELECT_MASK(drive, 0) ? */
|
||||
memset(&task, 0, sizeof(task));
|
||||
task.tf_flags = IDE_TFLAG_NO_SELECT_MASK; /* FIXME? */
|
||||
task.tf_flags |= (IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE);
|
||||
|
||||
if (drive->select.b.lba) {
|
||||
if (lba48) {
|
||||
task_ioreg_t tasklets[10];
|
||||
|
||||
pr_debug("%s: LBA=0x%012llx\n", drive->name,
|
||||
(unsigned long long)block);
|
||||
|
||||
tasklets[0] = 0;
|
||||
tasklets[1] = 0;
|
||||
tasklets[2] = nsectors.b.low;
|
||||
tasklets[3] = nsectors.b.high;
|
||||
tasklets[4] = (task_ioreg_t) block;
|
||||
tasklets[5] = (task_ioreg_t) (block>>8);
|
||||
tasklets[6] = (task_ioreg_t) (block>>16);
|
||||
tasklets[7] = (task_ioreg_t) (block>>24);
|
||||
if (sizeof(block) == 4) {
|
||||
tasklets[8] = (task_ioreg_t) 0;
|
||||
tasklets[9] = (task_ioreg_t) 0;
|
||||
} else {
|
||||
tasklets[8] = (task_ioreg_t)((u64)block >> 32);
|
||||
tasklets[9] = (task_ioreg_t)((u64)block >> 40);
|
||||
tf->hob_nsect = (nsectors >> 8) & 0xff;
|
||||
tf->hob_lbal = (u8)(block >> 24);
|
||||
if (sizeof(block) != 4) {
|
||||
tf->hob_lbam = (u8)((u64)block >> 32);
|
||||
tf->hob_lbah = (u8)((u64)block >> 40);
|
||||
}
|
||||
|
||||
tf->nsect = nsectors & 0xff;
|
||||
tf->lbal = (u8) block;
|
||||
tf->lbam = (u8)(block >> 8);
|
||||
tf->lbah = (u8)(block >> 16);
|
||||
#ifdef DEBUG
|
||||
printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n",
|
||||
drive->name, tasklets[3], tasklets[2],
|
||||
tasklets[9], tasklets[8], tasklets[7],
|
||||
tasklets[6], tasklets[5], tasklets[4]);
|
||||
drive->name, tf->hob_nsect, tf->nsect,
|
||||
tf->hob_lbah, tf->hob_lbam, tf->hob_lbal,
|
||||
tf->lbah, tf->lbam, tf->lbal);
|
||||
#endif
|
||||
hwif->OUTB(tasklets[1], IDE_FEATURE_REG);
|
||||
hwif->OUTB(tasklets[3], IDE_NSECTOR_REG);
|
||||
hwif->OUTB(tasklets[7], IDE_SECTOR_REG);
|
||||
hwif->OUTB(tasklets[8], IDE_LCYL_REG);
|
||||
hwif->OUTB(tasklets[9], IDE_HCYL_REG);
|
||||
|
||||
hwif->OUTB(tasklets[0], IDE_FEATURE_REG);
|
||||
hwif->OUTB(tasklets[2], IDE_NSECTOR_REG);
|
||||
hwif->OUTB(tasklets[4], IDE_SECTOR_REG);
|
||||
hwif->OUTB(tasklets[5], IDE_LCYL_REG);
|
||||
hwif->OUTB(tasklets[6], IDE_HCYL_REG);
|
||||
hwif->OUTB(0x00|drive->select.all,IDE_SELECT_REG);
|
||||
task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB);
|
||||
} else {
|
||||
hwif->OUTB(0x00, IDE_FEATURE_REG);
|
||||
hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG);
|
||||
hwif->OUTB(block, IDE_SECTOR_REG);
|
||||
hwif->OUTB(block>>=8, IDE_LCYL_REG);
|
||||
hwif->OUTB(block>>=8, IDE_HCYL_REG);
|
||||
hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
|
||||
tf->nsect = nsectors & 0xff;
|
||||
tf->lbal = block;
|
||||
tf->lbam = block >>= 8;
|
||||
tf->lbah = block >>= 8;
|
||||
tf->device = (block >> 8) & 0xf;
|
||||
}
|
||||
} else {
|
||||
unsigned int sect,head,cyl,track;
|
||||
track = (int)block / drive->sect;
|
||||
sect = (int)block % drive->sect + 1;
|
||||
hwif->OUTB(sect, IDE_SECTOR_REG);
|
||||
head = track % drive->head;
|
||||
cyl = track / drive->head;
|
||||
|
||||
pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
|
||||
|
||||
hwif->OUTB(0x00, IDE_FEATURE_REG);
|
||||
hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG);
|
||||
hwif->OUTB(cyl, IDE_LCYL_REG);
|
||||
hwif->OUTB(cyl>>8, IDE_HCYL_REG);
|
||||
hwif->OUTB(head|drive->select.all,IDE_SELECT_REG);
|
||||
tf->nsect = nsectors & 0xff;
|
||||
tf->lbal = sect;
|
||||
tf->lbam = cyl;
|
||||
tf->lbah = cyl >> 8;
|
||||
tf->device = head;
|
||||
}
|
||||
|
||||
if (dma) {
|
||||
if (!hwif->dma_setup(drive)) {
|
||||
if (rq_data_dir(rq)) {
|
||||
command = lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
|
||||
if (drive->vdma)
|
||||
command = lba48 ? WIN_WRITE_EXT: WIN_WRITE;
|
||||
} else {
|
||||
command = lba48 ? WIN_READDMA_EXT : WIN_READDMA;
|
||||
if (drive->vdma)
|
||||
command = lba48 ? WIN_READ_EXT: WIN_READ;
|
||||
}
|
||||
hwif->dma_exec_cmd(drive, command);
|
||||
hwif->dma_start(drive);
|
||||
return ide_started;
|
||||
}
|
||||
if (rq_data_dir(rq))
|
||||
task.tf_flags |= IDE_TFLAG_WRITE;
|
||||
|
||||
ide_tf_set_cmd(drive, &task, dma);
|
||||
if (!dma)
|
||||
hwif->data_phase = task.data_phase;
|
||||
task.rq = rq;
|
||||
|
||||
rc = do_rw_taskfile(drive, &task);
|
||||
|
||||
if (rc == ide_stopped && dma) {
|
||||
/* fallback to PIO */
|
||||
task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
|
||||
ide_tf_set_cmd(drive, &task, 0);
|
||||
hwif->data_phase = task.data_phase;
|
||||
ide_init_sg_cmd(drive, rq);
|
||||
rc = do_rw_taskfile(drive, &task);
|
||||
}
|
||||
|
||||
if (rq_data_dir(rq) == READ) {
|
||||
|
||||
if (drive->mult_count) {
|
||||
hwif->data_phase = TASKFILE_MULTI_IN;
|
||||
command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD;
|
||||
} else {
|
||||
hwif->data_phase = TASKFILE_IN;
|
||||
command = lba48 ? WIN_READ_EXT : WIN_READ;
|
||||
}
|
||||
|
||||
ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL);
|
||||
return ide_started;
|
||||
} else {
|
||||
if (drive->mult_count) {
|
||||
hwif->data_phase = TASKFILE_MULTI_OUT;
|
||||
command = lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
|
||||
} else {
|
||||
hwif->data_phase = TASKFILE_OUT;
|
||||
command = lba48 ? WIN_WRITE_EXT : WIN_WRITE;
|
||||
}
|
||||
|
||||
/* FIXME: ->OUTBSYNC ? */
|
||||
hwif->OUTB(command, IDE_COMMAND_REG);
|
||||
|
||||
return pre_task_out_intr(drive, rq);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -307,57 +306,29 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s
|
|||
* Queries for true maximum capacity of the drive.
|
||||
* Returns maximum LBA address (> 0) of the drive, 0 if failed.
|
||||
*/
|
||||
static unsigned long idedisk_read_native_max_address(ide_drive_t *drive)
|
||||
static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
|
||||
{
|
||||
ide_task_t args;
|
||||
unsigned long addr = 0;
|
||||
struct ide_taskfile *tf = &args.tf;
|
||||
u64 addr = 0;
|
||||
|
||||
/* Create IDE/ATA command request structure */
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX;
|
||||
args.command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args.handler = &task_no_data_intr;
|
||||
if (lba48)
|
||||
tf->command = WIN_READ_NATIVE_MAX_EXT;
|
||||
else
|
||||
tf->command = WIN_READ_NATIVE_MAX;
|
||||
tf->device = ATA_LBA;
|
||||
args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
if (lba48)
|
||||
args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB);
|
||||
/* submit command request */
|
||||
ide_raw_taskfile(drive, &args, NULL);
|
||||
ide_no_data_taskfile(drive, &args);
|
||||
|
||||
/* if OK, compute maximum address value */
|
||||
if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
|
||||
addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
|
||||
| ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16)
|
||||
| ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8)
|
||||
| ((args.tfRegister[IDE_SECTOR_OFFSET] ));
|
||||
addr++; /* since the return value is (maxlba - 1), we add 1 */
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
if ((tf->status & 0x01) == 0)
|
||||
addr = ide_get_lba_addr(tf, lba48) + 1;
|
||||
|
||||
static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive)
|
||||
{
|
||||
ide_task_t args;
|
||||
unsigned long long addr = 0;
|
||||
|
||||
/* Create IDE/ATA command request structure */
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
|
||||
args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT;
|
||||
args.command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args.handler = &task_no_data_intr;
|
||||
/* submit command request */
|
||||
ide_raw_taskfile(drive, &args, NULL);
|
||||
|
||||
/* if OK, compute maximum address value */
|
||||
if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
|
||||
u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) |
|
||||
(args.hobRegister[IDE_LCYL_OFFSET] << 8) |
|
||||
args.hobRegister[IDE_SECTOR_OFFSET];
|
||||
u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
|
||||
((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
|
||||
(args.tfRegister[IDE_SECTOR_OFFSET]);
|
||||
addr = ((__u64)high << 24) | low;
|
||||
addr++; /* since the return value is (maxlba - 1), we add 1 */
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
@ -365,67 +336,37 @@ static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive
|
|||
* Sets maximum virtual LBA address of the drive.
|
||||
* Returns new maximum virtual LBA address (> 0) or 0 on failure.
|
||||
*/
|
||||
static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req)
|
||||
static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
|
||||
{
|
||||
ide_task_t args;
|
||||
unsigned long addr_set = 0;
|
||||
struct ide_taskfile *tf = &args.tf;
|
||||
u64 addr_set = 0;
|
||||
|
||||
addr_req--;
|
||||
/* Create IDE/ATA command request structure */
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff);
|
||||
args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >> 8) & 0xff);
|
||||
args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >> 16) & 0xff);
|
||||
args.tfRegister[IDE_SELECT_OFFSET] = ((addr_req >> 24) & 0x0f) | 0x40;
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX;
|
||||
args.command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args.handler = &task_no_data_intr;
|
||||
/* submit command request */
|
||||
ide_raw_taskfile(drive, &args, NULL);
|
||||
/* if OK, read new maximum address value */
|
||||
if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
|
||||
addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
|
||||
| ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16)
|
||||
| ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8)
|
||||
| ((args.tfRegister[IDE_SECTOR_OFFSET] ));
|
||||
addr_set++;
|
||||
tf->lbal = (addr_req >> 0) & 0xff;
|
||||
tf->lbam = (addr_req >>= 8) & 0xff;
|
||||
tf->lbah = (addr_req >>= 8) & 0xff;
|
||||
if (lba48) {
|
||||
tf->hob_lbal = (addr_req >>= 8) & 0xff;
|
||||
tf->hob_lbam = (addr_req >>= 8) & 0xff;
|
||||
tf->hob_lbah = (addr_req >>= 8) & 0xff;
|
||||
tf->command = WIN_SET_MAX_EXT;
|
||||
} else {
|
||||
tf->device = (addr_req >>= 8) & 0x0f;
|
||||
tf->command = WIN_SET_MAX;
|
||||
}
|
||||
return addr_set;
|
||||
}
|
||||
|
||||
static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req)
|
||||
{
|
||||
ide_task_t args;
|
||||
unsigned long long addr_set = 0;
|
||||
|
||||
addr_req--;
|
||||
/* Create IDE/ATA command request structure */
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff);
|
||||
args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >>= 8) & 0xff);
|
||||
args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >>= 8) & 0xff);
|
||||
args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX_EXT;
|
||||
args.hobRegister[IDE_SECTOR_OFFSET] = (addr_req >>= 8) & 0xff;
|
||||
args.hobRegister[IDE_LCYL_OFFSET] = (addr_req >>= 8) & 0xff;
|
||||
args.hobRegister[IDE_HCYL_OFFSET] = (addr_req >>= 8) & 0xff;
|
||||
args.hobRegister[IDE_SELECT_OFFSET] = 0x40;
|
||||
args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
|
||||
args.command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args.handler = &task_no_data_intr;
|
||||
tf->device |= ATA_LBA;
|
||||
args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
if (lba48)
|
||||
args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB);
|
||||
/* submit command request */
|
||||
ide_raw_taskfile(drive, &args, NULL);
|
||||
ide_no_data_taskfile(drive, &args);
|
||||
/* if OK, compute maximum address value */
|
||||
if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
|
||||
u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) |
|
||||
(args.hobRegister[IDE_LCYL_OFFSET] << 8) |
|
||||
args.hobRegister[IDE_SECTOR_OFFSET];
|
||||
u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
|
||||
((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
|
||||
(args.tfRegister[IDE_SECTOR_OFFSET]);
|
||||
addr_set = ((__u64)high << 24) | low;
|
||||
addr_set++;
|
||||
}
|
||||
if ((tf->status & 0x01) == 0)
|
||||
addr_set = ide_get_lba_addr(tf, lba48) + 1;
|
||||
|
||||
return addr_set;
|
||||
}
|
||||
|
||||
|
@ -471,10 +412,8 @@ static void idedisk_check_hpa(ide_drive_t *drive)
|
|||
int lba48 = idedisk_supports_lba48(drive->id);
|
||||
|
||||
capacity = drive->capacity64;
|
||||
if (lba48)
|
||||
set_max = idedisk_read_native_max_address_ext(drive);
|
||||
else
|
||||
set_max = idedisk_read_native_max_address(drive);
|
||||
|
||||
set_max = idedisk_read_native_max_address(drive, lba48);
|
||||
|
||||
if (ide_in_drive_list(drive->id, hpa_list)) {
|
||||
/*
|
||||
|
@ -495,10 +434,8 @@ static void idedisk_check_hpa(ide_drive_t *drive)
|
|||
capacity, sectors_to_MB(capacity),
|
||||
set_max, sectors_to_MB(set_max));
|
||||
|
||||
if (lba48)
|
||||
set_max = idedisk_set_max_address_ext(drive, set_max);
|
||||
else
|
||||
set_max = idedisk_set_max_address(drive, set_max);
|
||||
set_max = idedisk_set_max_address(drive, set_max, lba48);
|
||||
|
||||
if (set_max) {
|
||||
drive->capacity64 = set_max;
|
||||
printk(KERN_INFO "%s: Host Protected Area disabled.\n",
|
||||
|
@ -556,32 +493,32 @@ static sector_t idedisk_capacity (ide_drive_t *drive)
|
|||
static int smart_enable(ide_drive_t *drive)
|
||||
{
|
||||
ide_task_t args;
|
||||
struct ide_taskfile *tf = &args.tf;
|
||||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.tfRegister[IDE_FEATURE_OFFSET] = SMART_ENABLE;
|
||||
args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
|
||||
args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART;
|
||||
args.command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args.handler = &task_no_data_intr;
|
||||
return ide_raw_taskfile(drive, &args, NULL);
|
||||
tf->feature = SMART_ENABLE;
|
||||
tf->lbam = SMART_LCYL_PASS;
|
||||
tf->lbah = SMART_HCYL_PASS;
|
||||
tf->command = WIN_SMART;
|
||||
args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
return ide_no_data_taskfile(drive, &args);
|
||||
}
|
||||
|
||||
static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
|
||||
{
|
||||
ide_task_t args;
|
||||
struct ide_taskfile *tf = &args.tf;
|
||||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.tfRegister[IDE_FEATURE_OFFSET] = sub_cmd;
|
||||
args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01;
|
||||
args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
|
||||
args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART;
|
||||
args.command_type = IDE_DRIVE_TASK_IN;
|
||||
tf->feature = sub_cmd;
|
||||
tf->nsect = 0x01;
|
||||
tf->lbam = SMART_LCYL_PASS;
|
||||
tf->lbah = SMART_HCYL_PASS;
|
||||
tf->command = WIN_SMART;
|
||||
args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
args.data_phase = TASKFILE_IN;
|
||||
args.handler = &task_in_intr;
|
||||
(void) smart_enable(drive);
|
||||
return ide_raw_taskfile(drive, &args, buf);
|
||||
return ide_raw_taskfile(drive, &args, buf, 1);
|
||||
}
|
||||
|
||||
static int proc_idedisk_read_cache
|
||||
|
@ -659,19 +596,20 @@ static ide_proc_entry_t idedisk_proc[] = {
|
|||
static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
|
||||
{
|
||||
ide_drive_t *drive = q->queuedata;
|
||||
ide_task_t task;
|
||||
|
||||
memset(rq->cmd, 0, sizeof(rq->cmd));
|
||||
|
||||
memset(&task, 0, sizeof(task));
|
||||
if (ide_id_has_flush_cache_ext(drive->id) &&
|
||||
(drive->capacity64 >= (1UL << 28)))
|
||||
rq->cmd[0] = WIN_FLUSH_CACHE_EXT;
|
||||
task.tf.command = WIN_FLUSH_CACHE_EXT;
|
||||
else
|
||||
rq->cmd[0] = WIN_FLUSH_CACHE;
|
||||
task.tf.command = WIN_FLUSH_CACHE;
|
||||
task.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
task.data_phase = TASKFILE_NO_DATA;
|
||||
|
||||
|
||||
rq->cmd_type = REQ_TYPE_ATA_TASK;
|
||||
rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
|
||||
rq->cmd_flags |= REQ_SOFTBARRIER;
|
||||
rq->buffer = rq->cmd;
|
||||
rq->special = &task;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -753,12 +691,11 @@ static int write_cache(ide_drive_t *drive, int arg)
|
|||
|
||||
if (ide_id_has_flush_cache(drive->id)) {
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ?
|
||||
args.tf.feature = arg ?
|
||||
SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES;
|
||||
args.command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args.handler = &task_no_data_intr;
|
||||
err = ide_raw_taskfile(drive, &args, NULL);
|
||||
args.tf.command = WIN_SETFEATURES;
|
||||
args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
err = ide_no_data_taskfile(drive, &args);
|
||||
if (err == 0)
|
||||
drive->wcache = arg;
|
||||
}
|
||||
|
@ -774,12 +711,11 @@ static int do_idedisk_flushcache (ide_drive_t *drive)
|
|||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
if (ide_id_has_flush_cache_ext(drive->id))
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
|
||||
args.tf.command = WIN_FLUSH_CACHE_EXT;
|
||||
else
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
|
||||
args.command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args.handler = &task_no_data_intr;
|
||||
return ide_raw_taskfile(drive, &args, NULL);
|
||||
args.tf.command = WIN_FLUSH_CACHE;
|
||||
args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
return ide_no_data_taskfile(drive, &args);
|
||||
}
|
||||
|
||||
static int set_acoustic (ide_drive_t *drive, int arg)
|
||||
|
@ -790,13 +726,11 @@ static int set_acoustic (ide_drive_t *drive, int arg)
|
|||
return -EINVAL;
|
||||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM :
|
||||
SETFEATURES_DIS_AAM;
|
||||
args.tfRegister[IDE_NSECTOR_OFFSET] = arg;
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES;
|
||||
args.command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args.handler = &task_no_data_intr;
|
||||
ide_raw_taskfile(drive, &args, NULL);
|
||||
args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM;
|
||||
args.tf.nsect = arg;
|
||||
args.tf.command = WIN_SETFEATURES;
|
||||
args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
ide_no_data_taskfile(drive, &args);
|
||||
drive->acoustic = arg;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1057,16 +991,15 @@ static int idedisk_open(struct inode *inode, struct file *filp)
|
|||
if (drive->removable && idkp->openers == 1) {
|
||||
ide_task_t args;
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
|
||||
args.command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args.handler = &task_no_data_intr;
|
||||
args.tf.command = WIN_DOORLOCK;
|
||||
args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
check_disk_change(inode->i_bdev);
|
||||
/*
|
||||
* Ignore the return code from door_lock,
|
||||
* since the open() has already succeeded,
|
||||
* and the door_lock is irrelevant at this point.
|
||||
*/
|
||||
if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
|
||||
if (drive->doorlocking && ide_no_data_taskfile(drive, &args))
|
||||
drive->doorlocking = 0;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1084,10 +1017,9 @@ static int idedisk_release(struct inode *inode, struct file *filp)
|
|||
if (drive->removable && idkp->openers == 1) {
|
||||
ide_task_t args;
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK;
|
||||
args.command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args.handler = &task_no_data_intr;
|
||||
if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
|
||||
args.tf.command = WIN_DOORUNLOCK;
|
||||
args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
if (drive->doorlocking && ide_no_data_taskfile(drive, &args))
|
||||
drive->doorlocking = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -491,10 +491,6 @@ EXPORT_SYMBOL(ide_dma_host_on);
|
|||
|
||||
int __ide_dma_on (ide_drive_t *drive)
|
||||
{
|
||||
/* consult the list of known "bad" drives */
|
||||
if (__ide_dma_bad_drive(drive))
|
||||
return 1;
|
||||
|
||||
drive->using_dma = 1;
|
||||
ide_toggle_bounce(drive, 1);
|
||||
|
||||
|
@ -827,22 +823,19 @@ int ide_set_dma(ide_drive_t *drive)
|
|||
ide_hwif_t *hwif = drive->hwif;
|
||||
int rc;
|
||||
|
||||
rc = ide_dma_check(drive);
|
||||
|
||||
switch(rc) {
|
||||
case -1: /* DMA needs to be disabled */
|
||||
/*
|
||||
* Force DMAing for the beginning of the check.
|
||||
* Some chipsets appear to do interesting
|
||||
* things, if not checked and cleared.
|
||||
* PARANOIA!!!
|
||||
*/
|
||||
hwif->dma_off_quietly(drive);
|
||||
return -1;
|
||||
case 0: /* DMA needs to be enabled */
|
||||
return hwif->ide_dma_on(drive);
|
||||
case 1: /* DMA setting cannot be changed */
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
||||
rc = ide_dma_check(drive);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return hwif->ide_dma_on(drive);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
|
||||
|
@ -968,11 +961,6 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
|
|||
|
||||
hwif->dma_base = base;
|
||||
|
||||
if (hwif->mate)
|
||||
hwif->dma_master = hwif->channel ? hwif->mate->dma_base : base;
|
||||
else
|
||||
hwif->dma_master = base;
|
||||
|
||||
if (!(hwif->dma_command))
|
||||
hwif->dma_command = hwif->dma_base;
|
||||
if (!(hwif->dma_vendor1))
|
||||
|
@ -1014,8 +1002,6 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
|
|||
hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
|
||||
}
|
||||
printk("\n");
|
||||
|
||||
BUG_ON(!hwif->dma_master);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_setup_dma);
|
||||
|
|
|
@ -369,27 +369,6 @@ typedef struct ide_floppy_obj {
|
|||
#define IDEFLOPPY_IOCTL_FORMAT_START 0x4602
|
||||
#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Special requests for our block device strategy routine.
|
||||
*/
|
||||
#define IDEFLOPPY_FIRST_RQ 90
|
||||
|
||||
/*
|
||||
* IDEFLOPPY_PC_RQ is used to queue a packet command in the request queue.
|
||||
*/
|
||||
#define IDEFLOPPY_PC_RQ 90
|
||||
|
||||
#define IDEFLOPPY_LAST_RQ 90
|
||||
|
||||
/*
|
||||
* A macro which can be used to check if a given request command
|
||||
* originated in the driver or in the buffer cache layer.
|
||||
*/
|
||||
#define IDEFLOPPY_RQ_CMD(cmd) ((cmd >= IDEFLOPPY_FIRST_RQ) && (cmd <= IDEFLOPPY_LAST_RQ))
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Error codes which are returned in rq->errors to the higher part
|
||||
* of the driver.
|
||||
|
@ -793,9 +772,8 @@ static void idefloppy_retry_pc (ide_drive_t *drive)
|
|||
{
|
||||
idefloppy_pc_t *pc;
|
||||
struct request *rq;
|
||||
atapi_error_t error;
|
||||
|
||||
error.all = HWIF(drive)->INB(IDE_ERROR_REG);
|
||||
(void)drive->hwif->INB(IDE_ERROR_REG);
|
||||
pc = idefloppy_next_pc_storage(drive);
|
||||
rq = idefloppy_next_rq_storage(drive);
|
||||
idefloppy_create_request_sense_cmd(pc);
|
||||
|
@ -809,12 +787,12 @@ static void idefloppy_retry_pc (ide_drive_t *drive)
|
|||
static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
|
||||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
atapi_status_t status;
|
||||
atapi_bcount_t bcount;
|
||||
atapi_ireason_t ireason;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
idefloppy_pc_t *pc = floppy->pc;
|
||||
struct request *rq = pc->rq;
|
||||
unsigned int temp;
|
||||
u16 bcount;
|
||||
u8 stat, ireason;
|
||||
|
||||
debug_log(KERN_INFO "ide-floppy: Reached %s interrupt handler\n",
|
||||
__FUNCTION__);
|
||||
|
@ -830,16 +808,16 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
|
|||
}
|
||||
|
||||
/* Clear the interrupt */
|
||||
status.all = HWIF(drive)->INB(IDE_STATUS_REG);
|
||||
stat = drive->hwif->INB(IDE_STATUS_REG);
|
||||
|
||||
if (!status.b.drq) { /* No more interrupts */
|
||||
if ((stat & DRQ_STAT) == 0) { /* No more interrupts */
|
||||
debug_log(KERN_INFO "Packet command completed, %d bytes "
|
||||
"transferred\n", pc->actually_transferred);
|
||||
clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);
|
||||
|
||||
local_irq_enable_in_hardirq();
|
||||
|
||||
if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) {
|
||||
if ((stat & ERR_STAT) || test_bit(PC_DMA_ERROR, &pc->flags)) {
|
||||
/* Error detected */
|
||||
debug_log(KERN_INFO "ide-floppy: %s: I/O error\n",
|
||||
drive->name);
|
||||
|
@ -870,32 +848,32 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
|
|||
}
|
||||
|
||||
/* Get the number of bytes to transfer */
|
||||
bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG);
|
||||
bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG);
|
||||
bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
|
||||
hwif->INB(IDE_BCOUNTL_REG);
|
||||
/* on this interrupt */
|
||||
ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
|
||||
ireason = hwif->INB(IDE_IREASON_REG);
|
||||
|
||||
if (ireason.b.cod) {
|
||||
if (ireason & CD) {
|
||||
printk(KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n");
|
||||
return ide_do_reset(drive);
|
||||
}
|
||||
if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) {
|
||||
if (((ireason & IO) == IO) == test_bit(PC_WRITING, &pc->flags)) {
|
||||
/* Hopefully, we will never get here */
|
||||
printk(KERN_ERR "ide-floppy: We wanted to %s, ",
|
||||
ireason.b.io ? "Write":"Read");
|
||||
(ireason & IO) ? "Write" : "Read");
|
||||
printk(KERN_ERR "but the floppy wants us to %s !\n",
|
||||
ireason.b.io ? "Read":"Write");
|
||||
(ireason & IO) ? "Read" : "Write");
|
||||
return ide_do_reset(drive);
|
||||
}
|
||||
if (!test_bit(PC_WRITING, &pc->flags)) {
|
||||
/* Reading - Check that we have enough space */
|
||||
temp = pc->actually_transferred + bcount.all;
|
||||
temp = pc->actually_transferred + bcount;
|
||||
if (temp > pc->request_transfer) {
|
||||
if (temp > pc->buffer_size) {
|
||||
printk(KERN_ERR "ide-floppy: The floppy wants "
|
||||
"to send us more data than expected "
|
||||
"- discarding data\n");
|
||||
idefloppy_discard_data(drive,bcount.all);
|
||||
idefloppy_discard_data(drive, bcount);
|
||||
BUG_ON(HWGROUP(drive)->handler != NULL);
|
||||
ide_set_handler(drive,
|
||||
&idefloppy_pc_intr,
|
||||
|
@ -911,23 +889,21 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
|
|||
if (test_bit(PC_WRITING, &pc->flags)) {
|
||||
if (pc->buffer != NULL)
|
||||
/* Write the current buffer */
|
||||
HWIF(drive)->atapi_output_bytes(drive,
|
||||
pc->current_position,
|
||||
bcount.all);
|
||||
hwif->atapi_output_bytes(drive, pc->current_position,
|
||||
bcount);
|
||||
else
|
||||
idefloppy_output_buffers(drive, pc, bcount.all);
|
||||
idefloppy_output_buffers(drive, pc, bcount);
|
||||
} else {
|
||||
if (pc->buffer != NULL)
|
||||
/* Read the current buffer */
|
||||
HWIF(drive)->atapi_input_bytes(drive,
|
||||
pc->current_position,
|
||||
bcount.all);
|
||||
hwif->atapi_input_bytes(drive, pc->current_position,
|
||||
bcount);
|
||||
else
|
||||
idefloppy_input_buffers(drive, pc, bcount.all);
|
||||
idefloppy_input_buffers(drive, pc, bcount);
|
||||
}
|
||||
/* Update the current position */
|
||||
pc->actually_transferred += bcount.all;
|
||||
pc->current_position += bcount.all;
|
||||
pc->actually_transferred += bcount;
|
||||
pc->current_position += bcount;
|
||||
|
||||
BUG_ON(HWGROUP(drive)->handler != NULL);
|
||||
ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */
|
||||
|
@ -943,15 +919,15 @@ static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive)
|
|||
{
|
||||
ide_startstop_t startstop;
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
atapi_ireason_t ireason;
|
||||
u8 ireason;
|
||||
|
||||
if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
|
||||
printk(KERN_ERR "ide-floppy: Strange, packet command "
|
||||
"initiated yet DRQ isn't asserted\n");
|
||||
return startstop;
|
||||
}
|
||||
ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
|
||||
if (!ireason.b.cod || ireason.b.io) {
|
||||
ireason = drive->hwif->INB(IDE_IREASON_REG);
|
||||
if ((ireason & CD) == 0 || (ireason & IO)) {
|
||||
printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while "
|
||||
"issuing a packet command\n");
|
||||
return ide_do_reset(drive);
|
||||
|
@ -991,15 +967,15 @@ static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive)
|
|||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
ide_startstop_t startstop;
|
||||
atapi_ireason_t ireason;
|
||||
u8 ireason;
|
||||
|
||||
if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
|
||||
printk(KERN_ERR "ide-floppy: Strange, packet command "
|
||||
"initiated yet DRQ isn't asserted\n");
|
||||
return startstop;
|
||||
}
|
||||
ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
|
||||
if (!ireason.b.cod || ireason.b.io) {
|
||||
ireason = drive->hwif->INB(IDE_IREASON_REG);
|
||||
if ((ireason & CD) == 0 || (ireason & IO)) {
|
||||
printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) "
|
||||
"while issuing a packet command\n");
|
||||
return ide_do_reset(drive);
|
||||
|
@ -1041,21 +1017,9 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
|
|||
{
|
||||
idefloppy_floppy_t *floppy = drive->driver_data;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
atapi_feature_t feature;
|
||||
atapi_bcount_t bcount;
|
||||
ide_handler_t *pkt_xfer_routine;
|
||||
|
||||
#if 0 /* Accessing floppy->pc is not valid here, the previous pc may be gone
|
||||
and have lived on another thread's stack; that stack may have become
|
||||
unmapped meanwhile (CONFIG_DEBUG_PAGEALLOC). */
|
||||
#if IDEFLOPPY_DEBUG_BUGS
|
||||
if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD &&
|
||||
pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
|
||||
printk(KERN_ERR "ide-floppy: possible ide-floppy.c bug - "
|
||||
"Two request sense in serial were issued\n");
|
||||
}
|
||||
#endif /* IDEFLOPPY_DEBUG_BUGS */
|
||||
#endif
|
||||
u16 bcount;
|
||||
u8 dma;
|
||||
|
||||
if (floppy->failed_pc == NULL &&
|
||||
pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD)
|
||||
|
@ -1093,25 +1057,20 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
|
|||
/* We haven't transferred any data yet */
|
||||
pc->actually_transferred = 0;
|
||||
pc->current_position = pc->buffer;
|
||||
bcount.all = min(pc->request_transfer, 63 * 1024);
|
||||
bcount = min(pc->request_transfer, 63 * 1024);
|
||||
|
||||
if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags))
|
||||
ide_dma_off(drive);
|
||||
|
||||
feature.all = 0;
|
||||
dma = 0;
|
||||
|
||||
if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
|
||||
feature.b.dma = !hwif->dma_setup(drive);
|
||||
dma = !hwif->dma_setup(drive);
|
||||
|
||||
if (IDE_CONTROL_REG)
|
||||
HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
|
||||
/* Use PIO/DMA */
|
||||
HWIF(drive)->OUTB(feature.all, IDE_FEATURE_REG);
|
||||
HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG);
|
||||
HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
|
||||
HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);
|
||||
ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
|
||||
IDE_TFLAG_OUT_DEVICE, bcount, dma);
|
||||
|
||||
if (feature.b.dma) { /* Begin DMA, if necessary */
|
||||
if (dma) { /* Begin DMA, if necessary */
|
||||
set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
|
||||
hwif->dma_start(drive);
|
||||
}
|
||||
|
@ -1665,14 +1624,14 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
|
|||
/* Else assume format_unit has finished, and we're
|
||||
** at 0x10000 */
|
||||
} else {
|
||||
atapi_status_t status;
|
||||
unsigned long flags;
|
||||
u8 stat;
|
||||
|
||||
local_irq_save(flags);
|
||||
status.all = HWIF(drive)->INB(IDE_STATUS_REG);
|
||||
stat = drive->hwif->INB(IDE_STATUS_REG);
|
||||
local_irq_restore(flags);
|
||||
|
||||
progress_indication = !status.b.dsc ? 0 : 0x10000;
|
||||
progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000;
|
||||
}
|
||||
if (put_user(progress_indication, arg))
|
||||
return (-EFAULT);
|
||||
|
|
|
@ -189,18 +189,14 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
|
|||
return ide_stopped;
|
||||
}
|
||||
if (ide_id_has_flush_cache_ext(drive->id))
|
||||
args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
|
||||
args->tf.command = WIN_FLUSH_CACHE_EXT;
|
||||
else
|
||||
args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
|
||||
args->command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args->handler = &task_no_data_intr;
|
||||
return do_rw_taskfile(drive, args);
|
||||
args->tf.command = WIN_FLUSH_CACHE;
|
||||
goto out_do_tf;
|
||||
|
||||
case idedisk_pm_standby: /* Suspend step 2 (standby) */
|
||||
args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1;
|
||||
args->command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args->handler = &task_no_data_intr;
|
||||
return do_rw_taskfile(drive, args);
|
||||
args->tf.command = WIN_STANDBYNOW1;
|
||||
goto out_do_tf;
|
||||
|
||||
case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */
|
||||
ide_set_max_pio(drive);
|
||||
|
@ -214,10 +210,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
|
|||
return ide_stopped;
|
||||
|
||||
case idedisk_pm_idle: /* Resume step 2 (idle) */
|
||||
args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE;
|
||||
args->command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args->handler = task_no_data_intr;
|
||||
return do_rw_taskfile(drive, args);
|
||||
args->tf.command = WIN_IDLEIMMEDIATE;
|
||||
goto out_do_tf;
|
||||
|
||||
case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */
|
||||
/*
|
||||
|
@ -227,7 +221,6 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
|
|||
*/
|
||||
if (drive->hwif->ide_dma_on == NULL)
|
||||
break;
|
||||
drive->hwif->dma_off_quietly(drive);
|
||||
/*
|
||||
* TODO: respect ->using_dma setting
|
||||
*/
|
||||
|
@ -236,6 +229,11 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
|
|||
}
|
||||
pm->pm_step = ide_pm_state_completed;
|
||||
return ide_stopped;
|
||||
|
||||
out_do_tf:
|
||||
args->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
args->data_phase = TASKFILE_NO_DATA;
|
||||
return do_rw_taskfile(drive, args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -298,6 +296,48 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
|
|||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
}
|
||||
|
||||
void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct ide_taskfile *tf = &task->tf;
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_IN_DATA) {
|
||||
u16 data = hwif->INW(IDE_DATA_REG);
|
||||
|
||||
tf->data = data & 0xff;
|
||||
tf->hob_data = (data >> 8) & 0xff;
|
||||
}
|
||||
|
||||
/* be sure we're looking at the low order bits */
|
||||
hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
|
||||
tf->nsect = hwif->INB(IDE_NSECTOR_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
|
||||
tf->lbal = hwif->INB(IDE_SECTOR_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_IN_LBAM)
|
||||
tf->lbam = hwif->INB(IDE_LCYL_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_IN_LBAH)
|
||||
tf->lbah = hwif->INB(IDE_HCYL_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
|
||||
tf->device = hwif->INB(IDE_SELECT_REG);
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_LBA48) {
|
||||
hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG);
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
|
||||
tf->hob_feature = hwif->INB(IDE_FEATURE_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
|
||||
tf->hob_nsect = hwif->INB(IDE_NSECTOR_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
|
||||
tf->hob_lbal = hwif->INB(IDE_SECTOR_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
|
||||
tf->hob_lbam = hwif->INB(IDE_LCYL_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
|
||||
tf->hob_lbah = hwif->INB(IDE_HCYL_REG);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_end_drive_cmd - end an explicit drive command
|
||||
* @drive: command
|
||||
|
@ -332,51 +372,22 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
|
|||
args[1] = err;
|
||||
args[2] = hwif->INB(IDE_NSECTOR_REG);
|
||||
}
|
||||
} else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
|
||||
u8 *args = (u8 *) rq->buffer;
|
||||
if (rq->errors == 0)
|
||||
rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
|
||||
|
||||
if (args) {
|
||||
args[0] = stat;
|
||||
args[1] = err;
|
||||
/* be sure we're looking at the low order bits */
|
||||
hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
|
||||
args[2] = hwif->INB(IDE_NSECTOR_REG);
|
||||
args[3] = hwif->INB(IDE_SECTOR_REG);
|
||||
args[4] = hwif->INB(IDE_LCYL_REG);
|
||||
args[5] = hwif->INB(IDE_HCYL_REG);
|
||||
args[6] = hwif->INB(IDE_SELECT_REG);
|
||||
}
|
||||
} else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
|
||||
ide_task_t *args = (ide_task_t *) rq->special;
|
||||
if (rq->errors == 0)
|
||||
rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
|
||||
|
||||
if (args) {
|
||||
if (args->tf_in_flags.b.data) {
|
||||
u16 data = hwif->INW(IDE_DATA_REG);
|
||||
args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF;
|
||||
args->hobRegister[IDE_DATA_OFFSET] = (data >> 8) & 0xFF;
|
||||
}
|
||||
args->tfRegister[IDE_ERROR_OFFSET] = err;
|
||||
/* be sure we're looking at the low order bits */
|
||||
hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
|
||||
args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
|
||||
args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG);
|
||||
args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG);
|
||||
args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG);
|
||||
args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG);
|
||||
args->tfRegister[IDE_STATUS_OFFSET] = stat;
|
||||
struct ide_taskfile *tf = &args->tf;
|
||||
|
||||
if (drive->addressing == 1) {
|
||||
hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
|
||||
args->hobRegister[IDE_FEATURE_OFFSET] = hwif->INB(IDE_FEATURE_REG);
|
||||
args->hobRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
|
||||
args->hobRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG);
|
||||
args->hobRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG);
|
||||
args->hobRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG);
|
||||
}
|
||||
tf->error = err;
|
||||
tf->status = stat;
|
||||
|
||||
args->tf_flags |= (IDE_TFLAG_IN_TF|IDE_TFLAG_IN_DEVICE);
|
||||
if (args->tf_flags & IDE_TFLAG_LBA48)
|
||||
args->tf_flags |= IDE_TFLAG_IN_HOB;
|
||||
|
||||
ide_tf_read(drive, args);
|
||||
}
|
||||
} else if (blk_pm_request(rq)) {
|
||||
struct request_pm_state *pm = rq->data;
|
||||
|
@ -615,28 +626,6 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
|
|||
return __ide_abort(drive, rq);
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_cmd - issue a simple drive command
|
||||
* @drive: drive the command is for
|
||||
* @cmd: command byte
|
||||
* @nsect: sector byte
|
||||
* @handler: handler for the command completion
|
||||
*
|
||||
* Issue a simple drive command with interrupts.
|
||||
* The drive must be selected beforehand.
|
||||
*/
|
||||
|
||||
static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect,
|
||||
ide_handler_t *handler)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
if (IDE_CONTROL_REG)
|
||||
hwif->OUTB(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */
|
||||
SELECT_MASK(drive,0);
|
||||
hwif->OUTB(nsect,IDE_NSECTOR_REG);
|
||||
ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* drive_cmd_intr - drive command completion interrupt
|
||||
* @drive: drive the completion interrupt occurred on
|
||||
|
@ -673,32 +662,26 @@ static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
|
|||
return ide_stopped;
|
||||
}
|
||||
|
||||
static void ide_init_specify_cmd(ide_drive_t *drive, ide_task_t *task)
|
||||
static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
|
||||
{
|
||||
task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
|
||||
task->tfRegister[IDE_SECTOR_OFFSET] = drive->sect;
|
||||
task->tfRegister[IDE_LCYL_OFFSET] = drive->cyl;
|
||||
task->tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8;
|
||||
task->tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF;
|
||||
task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY;
|
||||
|
||||
task->handler = &set_geometry_intr;
|
||||
tf->nsect = drive->sect;
|
||||
tf->lbal = drive->sect;
|
||||
tf->lbam = drive->cyl;
|
||||
tf->lbah = drive->cyl >> 8;
|
||||
tf->device = ((drive->head - 1) | drive->select.all) & ~ATA_LBA;
|
||||
tf->command = WIN_SPECIFY;
|
||||
}
|
||||
|
||||
static void ide_init_restore_cmd(ide_drive_t *drive, ide_task_t *task)
|
||||
static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
|
||||
{
|
||||
task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
|
||||
task->tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE;
|
||||
|
||||
task->handler = &recal_intr;
|
||||
tf->nsect = drive->sect;
|
||||
tf->command = WIN_RESTORE;
|
||||
}
|
||||
|
||||
static void ide_init_setmult_cmd(ide_drive_t *drive, ide_task_t *task)
|
||||
static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
|
||||
{
|
||||
task->tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req;
|
||||
task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT;
|
||||
|
||||
task->handler = &set_multmode_intr;
|
||||
tf->nsect = drive->mult_req;
|
||||
tf->command = WIN_SETMULT;
|
||||
}
|
||||
|
||||
static ide_startstop_t ide_disk_special(ide_drive_t *drive)
|
||||
|
@ -707,19 +690,19 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
|
|||
ide_task_t args;
|
||||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.command_type = IDE_DRIVE_TASK_NO_DATA;
|
||||
args.data_phase = TASKFILE_NO_DATA;
|
||||
|
||||
if (s->b.set_geometry) {
|
||||
s->b.set_geometry = 0;
|
||||
ide_init_specify_cmd(drive, &args);
|
||||
ide_tf_set_specify_cmd(drive, &args.tf);
|
||||
} else if (s->b.recalibrate) {
|
||||
s->b.recalibrate = 0;
|
||||
ide_init_restore_cmd(drive, &args);
|
||||
ide_tf_set_restore_cmd(drive, &args.tf);
|
||||
} else if (s->b.set_multmode) {
|
||||
s->b.set_multmode = 0;
|
||||
if (drive->mult_req > drive->id->max_multsect)
|
||||
drive->mult_req = drive->id->max_multsect;
|
||||
ide_init_setmult_cmd(drive, &args);
|
||||
ide_tf_set_setmult_cmd(drive, &args.tf);
|
||||
} else if (s->all) {
|
||||
int special = s->all;
|
||||
s->all = 0;
|
||||
|
@ -727,6 +710,9 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
|
|||
return ide_stopped;
|
||||
}
|
||||
|
||||
args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
|
||||
IDE_TFLAG_CUSTOM_HANDLER;
|
||||
|
||||
do_rw_taskfile(drive, &args);
|
||||
|
||||
return ide_started;
|
||||
|
@ -861,13 +847,17 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
|
|||
struct request *rq)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
|
||||
ide_task_t *args = rq->special;
|
||||
u8 *args = rq->buffer;
|
||||
ide_task_t ltask;
|
||||
struct ide_taskfile *tf = <ask.tf;
|
||||
|
||||
if (!args)
|
||||
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
|
||||
ide_task_t *task = rq->special;
|
||||
|
||||
if (task == NULL)
|
||||
goto done;
|
||||
|
||||
hwif->data_phase = args->data_phase;
|
||||
hwif->data_phase = task->data_phase;
|
||||
|
||||
switch (hwif->data_phase) {
|
||||
case TASKFILE_MULTI_OUT:
|
||||
|
@ -880,55 +870,34 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
|
|||
break;
|
||||
}
|
||||
|
||||
if (args->tf_out_flags.all != 0)
|
||||
return flagged_taskfile(drive, args);
|
||||
return do_rw_taskfile(drive, args);
|
||||
} else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
|
||||
u8 *args = rq->buffer;
|
||||
return do_rw_taskfile(drive, task);
|
||||
}
|
||||
|
||||
if (!args)
|
||||
if (args == NULL)
|
||||
goto done;
|
||||
#ifdef DEBUG
|
||||
printk("%s: DRIVE_TASK_CMD ", drive->name);
|
||||
printk("cmd=0x%02x ", args[0]);
|
||||
printk("fr=0x%02x ", args[1]);
|
||||
printk("ns=0x%02x ", args[2]);
|
||||
printk("sc=0x%02x ", args[3]);
|
||||
printk("lcyl=0x%02x ", args[4]);
|
||||
printk("hcyl=0x%02x ", args[5]);
|
||||
printk("sel=0x%02x\n", args[6]);
|
||||
#endif
|
||||
hwif->OUTB(args[1], IDE_FEATURE_REG);
|
||||
hwif->OUTB(args[3], IDE_SECTOR_REG);
|
||||
hwif->OUTB(args[4], IDE_LCYL_REG);
|
||||
hwif->OUTB(args[5], IDE_HCYL_REG);
|
||||
hwif->OUTB((args[6] & 0xEF)|drive->select.all, IDE_SELECT_REG);
|
||||
ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
|
||||
return ide_started;
|
||||
} else if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
|
||||
u8 *args = rq->buffer;
|
||||
|
||||
if (!args)
|
||||
goto done;
|
||||
memset(<ask, 0, sizeof(ltask));
|
||||
if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
|
||||
#ifdef DEBUG
|
||||
printk("%s: DRIVE_CMD ", drive->name);
|
||||
printk("cmd=0x%02x ", args[0]);
|
||||
printk("sc=0x%02x ", args[1]);
|
||||
printk("fr=0x%02x ", args[2]);
|
||||
printk("xx=0x%02x\n", args[3]);
|
||||
printk("%s: DRIVE_CMD\n", drive->name);
|
||||
#endif
|
||||
tf->feature = args[2];
|
||||
if (args[0] == WIN_SMART) {
|
||||
hwif->OUTB(0x4f, IDE_LCYL_REG);
|
||||
hwif->OUTB(0xc2, IDE_HCYL_REG);
|
||||
hwif->OUTB(args[2],IDE_FEATURE_REG);
|
||||
hwif->OUTB(args[1],IDE_SECTOR_REG);
|
||||
ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
|
||||
return ide_started;
|
||||
tf->nsect = args[3];
|
||||
tf->lbal = args[1];
|
||||
tf->lbam = 0x4f;
|
||||
tf->lbah = 0xc2;
|
||||
ltask.tf_flags = IDE_TFLAG_OUT_TF;
|
||||
} else {
|
||||
tf->nsect = args[1];
|
||||
ltask.tf_flags = IDE_TFLAG_OUT_FEATURE |
|
||||
IDE_TFLAG_OUT_NSECT;
|
||||
}
|
||||
hwif->OUTB(args[2],IDE_FEATURE_REG);
|
||||
ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
|
||||
return ide_started;
|
||||
}
|
||||
tf->command = args[0];
|
||||
ide_tf_load(drive, <ask);
|
||||
ide_execute_command(drive, args[0], &drive_cmd_intr, WAIT_WORSTCASE, NULL);
|
||||
return ide_started;
|
||||
|
||||
done:
|
||||
/*
|
||||
|
@ -1003,6 +972,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
|
|||
|
||||
/* bail early if we've exceeded max_failures */
|
||||
if (drive->max_failures && (drive->failures > drive->max_failures)) {
|
||||
rq->cmd_flags |= REQ_FAILED;
|
||||
goto kill_rq;
|
||||
}
|
||||
|
||||
|
@ -1035,7 +1005,6 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
|
|||
ide_config_drive_speed(drive, drive->desired_speed);
|
||||
|
||||
if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
|
||||
rq->cmd_type == REQ_TYPE_ATA_TASK ||
|
||||
rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
|
||||
return execute_drive_cmd(drive, rq);
|
||||
else if (blk_pm_request(rq)) {
|
||||
|
@ -1247,8 +1216,12 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
|
|||
if (hwgroup->hwif->sharing_irq &&
|
||||
hwif != hwgroup->hwif &&
|
||||
hwif->io_ports[IDE_CONTROL_OFFSET]) {
|
||||
/* set nIEN for previous hwif */
|
||||
SELECT_INTERRUPT(drive);
|
||||
/*
|
||||
* set nIEN for previous hwif, drives in the
|
||||
* quirk_list may not like intr setups/cleanups
|
||||
*/
|
||||
if (drive->quirk_list != 1)
|
||||
hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG);
|
||||
}
|
||||
hwgroup->hwif = hwif;
|
||||
hwgroup->drive = drive;
|
||||
|
@ -1454,12 +1427,8 @@ void ide_timer_expiry (unsigned long data)
|
|||
*/
|
||||
spin_unlock(&ide_lock);
|
||||
hwif = HWIF(drive);
|
||||
#if DISABLE_IRQ_NOSYNC
|
||||
disable_irq_nosync(hwif->irq);
|
||||
#else
|
||||
/* disable_irq_nosync ?? */
|
||||
disable_irq(hwif->irq);
|
||||
#endif /* DISABLE_IRQ_NOSYNC */
|
||||
/* local CPU only,
|
||||
* as if we were handling an interrupt */
|
||||
local_irq_disable();
|
||||
|
@ -1785,3 +1754,19 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
|
|||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_do_drive_cmd);
|
||||
|
||||
void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
|
||||
{
|
||||
ide_task_t task;
|
||||
|
||||
memset(&task, 0, sizeof(task));
|
||||
task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
|
||||
IDE_TFLAG_OUT_FEATURE | tf_flags;
|
||||
task.tf.feature = dma; /* Use PIO/DMA */
|
||||
task.tf.lbam = bcount & 0xff;
|
||||
task.tf.lbah = (bcount >> 8) & 0xff;
|
||||
|
||||
ide_tf_load(drive, &task);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
|
||||
|
|
|
@ -158,14 +158,6 @@ void default_hwif_mmiops (ide_hwif_t *hwif)
|
|||
|
||||
EXPORT_SYMBOL(default_hwif_mmiops);
|
||||
|
||||
u32 ide_read_24 (ide_drive_t *drive)
|
||||
{
|
||||
u8 hcyl = HWIF(drive)->INB(IDE_HCYL_REG);
|
||||
u8 lcyl = HWIF(drive)->INB(IDE_LCYL_REG);
|
||||
u8 sect = HWIF(drive)->INB(IDE_SECTOR_REG);
|
||||
return (hcyl<<16)|(lcyl<<8)|sect;
|
||||
}
|
||||
|
||||
void SELECT_DRIVE (ide_drive_t *drive)
|
||||
{
|
||||
if (HWIF(drive)->selectproc)
|
||||
|
@ -175,26 +167,12 @@ void SELECT_DRIVE (ide_drive_t *drive)
|
|||
|
||||
EXPORT_SYMBOL(SELECT_DRIVE);
|
||||
|
||||
void SELECT_INTERRUPT (ide_drive_t *drive)
|
||||
{
|
||||
if (HWIF(drive)->intrproc)
|
||||
HWIF(drive)->intrproc(drive);
|
||||
else
|
||||
HWIF(drive)->OUTB(drive->ctl|2, IDE_CONTROL_REG);
|
||||
}
|
||||
|
||||
void SELECT_MASK (ide_drive_t *drive, int mask)
|
||||
{
|
||||
if (HWIF(drive)->maskproc)
|
||||
HWIF(drive)->maskproc(drive, mask);
|
||||
}
|
||||
|
||||
void QUIRK_LIST (ide_drive_t *drive)
|
||||
{
|
||||
if (HWIF(drive)->quirkproc)
|
||||
drive->quirk_list = HWIF(drive)->quirkproc(drive);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some localbus EIDE interfaces require a special access sequence
|
||||
* when using 32-bit I/O instructions to transfer data. We call this
|
||||
|
@ -449,7 +427,6 @@ int drive_is_ready (ide_drive_t *drive)
|
|||
udelay(1);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IDEPCI_SHARE_IRQ
|
||||
/*
|
||||
* We do a passive status test under shared PCI interrupts on
|
||||
* cards that truly share the ATA side interrupt, but may also share
|
||||
|
@ -459,7 +436,6 @@ int drive_is_ready (ide_drive_t *drive)
|
|||
if (IDE_CONTROL_REG)
|
||||
stat = hwif->INB(IDE_ALTSTATUS_REG);
|
||||
else
|
||||
#endif /* CONFIG_IDEPCI_SHARE_IRQ */
|
||||
/* Note: this may clear a pending IRQ!! */
|
||||
stat = hwif->INB(IDE_STATUS_REG);
|
||||
|
||||
|
@ -642,9 +618,9 @@ no_80w:
|
|||
|
||||
int ide_ata66_check (ide_drive_t *drive, ide_task_t *args)
|
||||
{
|
||||
if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
|
||||
(args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) &&
|
||||
(args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) {
|
||||
if (args->tf.command == WIN_SETFEATURES &&
|
||||
args->tf.lbal > XFER_UDMA_2 &&
|
||||
args->tf.feature == SETFEATURES_XFER) {
|
||||
if (eighty_ninty_three(drive) == 0) {
|
||||
printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
|
||||
"be set\n", drive->name);
|
||||
|
@ -662,9 +638,9 @@ int ide_ata66_check (ide_drive_t *drive, ide_task_t *args)
|
|||
*/
|
||||
int set_transfer (ide_drive_t *drive, ide_task_t *args)
|
||||
{
|
||||
if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
|
||||
(args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) &&
|
||||
(args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) &&
|
||||
if (args->tf.command == WIN_SETFEATURES &&
|
||||
args->tf.lbal >= XFER_SW_DMA_0 &&
|
||||
args->tf.feature == SETFEATURES_XFER &&
|
||||
(drive->id->dma_ultra ||
|
||||
drive->id->dma_mword ||
|
||||
drive->id->dma_1word))
|
||||
|
@ -903,7 +879,8 @@ EXPORT_SYMBOL(ide_set_handler);
|
|||
* should go via this function or do equivalent locking.
|
||||
*/
|
||||
|
||||
void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *handler, unsigned timeout, ide_expiry_t *expiry)
|
||||
void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
|
||||
unsigned timeout, ide_expiry_t *expiry)
|
||||
{
|
||||
unsigned long flags;
|
||||
ide_hwgroup_t *hwgroup = HWGROUP(drive);
|
||||
|
@ -1051,7 +1028,6 @@ static void ide_disk_pre_reset(ide_drive_t *drive)
|
|||
drive->special.all = 0;
|
||||
drive->special.b.set_geometry = legacy;
|
||||
drive->special.b.recalibrate = legacy;
|
||||
if (OK_TO_RESET_CONTROLLER)
|
||||
drive->mult_count = 0;
|
||||
if (!drive->keep_settings && !drive->using_dma)
|
||||
drive->mult_req = 0;
|
||||
|
@ -1137,7 +1113,6 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
|
|||
for (unit = 0; unit < MAX_DRIVES; ++unit)
|
||||
pre_reset(&hwif->drives[unit]);
|
||||
|
||||
#if OK_TO_RESET_CONTROLLER
|
||||
if (!IDE_CONTROL_REG) {
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
return ide_stopped;
|
||||
|
@ -1174,11 +1149,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
|
|||
* state when the disks are reset this way. At least, the Winbond
|
||||
* 553 documentation says that
|
||||
*/
|
||||
if (hwif->resetproc != NULL) {
|
||||
if (hwif->resetproc)
|
||||
hwif->resetproc(drive);
|
||||
}
|
||||
|
||||
#endif /* OK_TO_RESET_CONTROLLER */
|
||||
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
return ide_started;
|
||||
|
|
|
@ -441,6 +441,12 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
|
|||
* case could happen iff the transfer mode has already been set on
|
||||
* the device by ide-proc.c::set_xfer_rate()).
|
||||
*/
|
||||
if (rate < XFER_PIO_0) {
|
||||
if (hwif->host_flags & IDE_HFLAG_ABUSE_SET_DMA_MODE)
|
||||
return ide_set_dma_mode(drive, rate);
|
||||
else
|
||||
return ide_config_drive_speed(drive, rate);
|
||||
}
|
||||
|
||||
return ide_set_dma_mode(drive, rate);
|
||||
}
|
||||
|
@ -458,8 +464,7 @@ static void ide_dump_opcode(ide_drive_t *drive)
|
|||
spin_unlock(&ide_lock);
|
||||
if (!rq)
|
||||
return;
|
||||
if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
|
||||
rq->cmd_type == REQ_TYPE_ATA_TASK) {
|
||||
if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
|
||||
char *args = rq->buffer;
|
||||
if (args) {
|
||||
opcode = args[0];
|
||||
|
@ -468,8 +473,7 @@ static void ide_dump_opcode(ide_drive_t *drive)
|
|||
} else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
|
||||
ide_task_t *args = rq->special;
|
||||
if (args) {
|
||||
task_struct_t *tf = (task_struct_t *) args->tfRegister;
|
||||
opcode = tf->command;
|
||||
opcode = args->tf.command;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
@ -481,9 +485,90 @@ static void ide_dump_opcode(ide_drive_t *drive)
|
|||
printk("0x%02x\n", opcode);
|
||||
}
|
||||
|
||||
static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
|
||||
u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48)
|
||||
{
|
||||
u32 high, low;
|
||||
|
||||
if (lba48)
|
||||
high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) |
|
||||
tf->hob_lbal;
|
||||
else
|
||||
high = tf->device & 0xf;
|
||||
low = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal;
|
||||
|
||||
return ((u64)high << 24) | low;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_get_lba_addr);
|
||||
|
||||
static void ide_dump_sector(ide_drive_t *drive)
|
||||
{
|
||||
ide_task_t task;
|
||||
struct ide_taskfile *tf = &task.tf;
|
||||
int lba48 = (drive->addressing == 1) ? 1 : 0;
|
||||
|
||||
memset(&task, 0, sizeof(task));
|
||||
if (lba48)
|
||||
task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA |
|
||||
IDE_TFLAG_LBA48;
|
||||
else
|
||||
task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
|
||||
|
||||
ide_tf_read(drive, &task);
|
||||
|
||||
if (lba48 || (tf->device & ATA_LBA))
|
||||
printk(", LBAsect=%llu",
|
||||
(unsigned long long)ide_get_lba_addr(tf, lba48));
|
||||
else
|
||||
printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
|
||||
tf->device & 0xf, tf->lbal);
|
||||
}
|
||||
|
||||
static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
|
||||
{
|
||||
printk("{ ");
|
||||
if (err & ABRT_ERR) printk("DriveStatusError ");
|
||||
if (err & ICRC_ERR)
|
||||
printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
|
||||
if (err & ECC_ERR) printk("UncorrectableError ");
|
||||
if (err & ID_ERR) printk("SectorIdNotFound ");
|
||||
if (err & TRK0_ERR) printk("TrackZeroNotFound ");
|
||||
if (err & MARK_ERR) printk("AddrMarkNotFound ");
|
||||
printk("}");
|
||||
if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
|
||||
(err & (ECC_ERR|ID_ERR|MARK_ERR))) {
|
||||
ide_dump_sector(drive);
|
||||
if (HWGROUP(drive) && HWGROUP(drive)->rq)
|
||||
printk(", sector=%llu",
|
||||
(unsigned long long)HWGROUP(drive)->rq->sector);
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
|
||||
{
|
||||
printk("{ ");
|
||||
if (err & ILI_ERR) printk("IllegalLengthIndication ");
|
||||
if (err & EOM_ERR) printk("EndOfMedia ");
|
||||
if (err & ABRT_ERR) printk("AbortedCommand ");
|
||||
if (err & MCR_ERR) printk("MediaChangeRequested ");
|
||||
if (err & LFS_ERR) printk("LastFailedSense=0x%02x ",
|
||||
(err & LFS_ERR) >> 4);
|
||||
printk("}\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_dump_status - translate ATA/ATAPI error
|
||||
* @drive: drive that status applies to
|
||||
* @msg: text message to print
|
||||
* @stat: status byte to decode
|
||||
*
|
||||
* Error reporting, in human readable form (luxurious, but a memory hog).
|
||||
* Combines the drive name, message and status byte to provide a
|
||||
* user understandable explanation of the device error.
|
||||
*/
|
||||
|
||||
u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
unsigned long flags;
|
||||
u8 err = 0;
|
||||
|
||||
|
@ -502,120 +587,16 @@ static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
|
|||
}
|
||||
printk("}\n");
|
||||
if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
|
||||
err = hwif->INB(IDE_ERROR_REG);
|
||||
printk("%s: %s: error=0x%02x { ", drive->name, msg, err);
|
||||
if (err & ABRT_ERR) printk("DriveStatusError ");
|
||||
if (err & ICRC_ERR)
|
||||
printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
|
||||
if (err & ECC_ERR) printk("UncorrectableError ");
|
||||
if (err & ID_ERR) printk("SectorIdNotFound ");
|
||||
if (err & TRK0_ERR) printk("TrackZeroNotFound ");
|
||||
if (err & MARK_ERR) printk("AddrMarkNotFound ");
|
||||
printk("}");
|
||||
if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
|
||||
(err & (ECC_ERR|ID_ERR|MARK_ERR))) {
|
||||
if (drive->addressing == 1) {
|
||||
__u64 sectors = 0;
|
||||
u32 low = 0, high = 0;
|
||||
hwif->OUTB(drive->ctl&~0x80, IDE_CONTROL_REG);
|
||||
low = ide_read_24(drive);
|
||||
hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
|
||||
high = ide_read_24(drive);
|
||||
sectors = ((__u64)high << 24) | low;
|
||||
printk(", LBAsect=%llu, high=%d, low=%d",
|
||||
(unsigned long long) sectors,
|
||||
high, low);
|
||||
} else {
|
||||
u8 cur = hwif->INB(IDE_SELECT_REG);
|
||||
if (cur & 0x40) { /* using LBA? */
|
||||
printk(", LBAsect=%ld", (unsigned long)
|
||||
((cur&0xf)<<24)
|
||||
|(hwif->INB(IDE_HCYL_REG)<<16)
|
||||
|(hwif->INB(IDE_LCYL_REG)<<8)
|
||||
| hwif->INB(IDE_SECTOR_REG));
|
||||
} else {
|
||||
printk(", CHS=%d/%d/%d",
|
||||
(hwif->INB(IDE_HCYL_REG)<<8) +
|
||||
hwif->INB(IDE_LCYL_REG),
|
||||
cur & 0xf,
|
||||
hwif->INB(IDE_SECTOR_REG));
|
||||
}
|
||||
}
|
||||
if (HWGROUP(drive) && HWGROUP(drive)->rq)
|
||||
printk(", sector=%llu",
|
||||
(unsigned long long)HWGROUP(drive)->rq->sector);
|
||||
}
|
||||
printk("\n");
|
||||
err = drive->hwif->INB(IDE_ERROR_REG);
|
||||
printk("%s: %s: error=0x%02x ", drive->name, msg, err);
|
||||
if (drive->media == ide_disk)
|
||||
ide_dump_ata_error(drive, err);
|
||||
else
|
||||
ide_dump_atapi_error(drive, err);
|
||||
}
|
||||
ide_dump_opcode(drive);
|
||||
local_irq_restore(flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_dump_atapi_status - print human readable atapi status
|
||||
* @drive: drive that status applies to
|
||||
* @msg: text message to print
|
||||
* @stat: status byte to decode
|
||||
*
|
||||
* Error reporting, in human readable form (luxurious, but a memory hog).
|
||||
*/
|
||||
|
||||
static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
atapi_status_t status;
|
||||
atapi_error_t error;
|
||||
|
||||
status.all = stat;
|
||||
error.all = 0;
|
||||
local_irq_save(flags);
|
||||
printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
|
||||
if (status.b.bsy)
|
||||
printk("Busy ");
|
||||
else {
|
||||
if (status.b.drdy) printk("DriveReady ");
|
||||
if (status.b.df) printk("DeviceFault ");
|
||||
if (status.b.dsc) printk("SeekComplete ");
|
||||
if (status.b.drq) printk("DataRequest ");
|
||||
if (status.b.corr) printk("CorrectedError ");
|
||||
if (status.b.idx) printk("Index ");
|
||||
if (status.b.check) printk("Error ");
|
||||
}
|
||||
printk("}\n");
|
||||
if (status.b.check && !status.b.bsy) {
|
||||
error.all = HWIF(drive)->INB(IDE_ERROR_REG);
|
||||
printk("%s: %s: error=0x%02x { ", drive->name, msg, error.all);
|
||||
if (error.b.ili) printk("IllegalLengthIndication ");
|
||||
if (error.b.eom) printk("EndOfMedia ");
|
||||
if (error.b.abrt) printk("AbortedCommand ");
|
||||
if (error.b.mcr) printk("MediaChangeRequested ");
|
||||
if (error.b.sense_key) printk("LastFailedSense=0x%02x ",
|
||||
error.b.sense_key);
|
||||
printk("}\n");
|
||||
}
|
||||
ide_dump_opcode(drive);
|
||||
local_irq_restore(flags);
|
||||
return error.all;
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_dump_status - translate ATA/ATAPI error
|
||||
* @drive: drive the error occured on
|
||||
* @msg: information string
|
||||
* @stat: status byte
|
||||
*
|
||||
* Error reporting, in human readable form (luxurious, but a memory hog).
|
||||
* Combines the drive name, message and status byte to provide a
|
||||
* user understandable explanation of the device error.
|
||||
*/
|
||||
|
||||
u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
|
||||
{
|
||||
if (drive->media == ide_disk)
|
||||
return ide_dump_ata_status(drive, msg, stat);
|
||||
return ide_dump_atapi_status(drive, msg, stat);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_dump_status);
|
||||
|
|
|
@ -95,10 +95,10 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
|
|||
#ifdef CONFIG_IDEDISK_MULTI_MODE
|
||||
id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
|
||||
id->multsect_valid = id->multsect ? 1 : 0;
|
||||
drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
|
||||
drive->mult_req = id->multsect_valid ? id->max_multsect : 0;
|
||||
drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
|
||||
#else /* original, pre IDE-NFG, per request of AC */
|
||||
drive->mult_req = INITIAL_MULT_COUNT;
|
||||
drive->mult_req = 0;
|
||||
if (drive->mult_req > id->max_multsect)
|
||||
drive->mult_req = id->max_multsect;
|
||||
if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
|
||||
|
@ -234,7 +234,10 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
|
|||
|
||||
drive->media = ide_disk;
|
||||
printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" );
|
||||
QUIRK_LIST(drive);
|
||||
|
||||
if (hwif->quirkproc)
|
||||
drive->quirk_list = hwif->quirkproc(drive);
|
||||
|
||||
return;
|
||||
|
||||
err_misc:
|
||||
|
@ -830,18 +833,10 @@ static void probe_hwif(ide_hwif_t *hwif)
|
|||
|
||||
drive->nice1 = 1;
|
||||
|
||||
if (hwif->ide_dma_on) {
|
||||
/*
|
||||
* Force DMAing for the beginning of the check.
|
||||
* Some chipsets appear to do interesting
|
||||
* things, if not checked and cleared.
|
||||
* PARANOIA!!!
|
||||
*/
|
||||
hwif->dma_off_quietly(drive);
|
||||
if (hwif->ide_dma_on)
|
||||
ide_set_dma(drive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unit = 0; unit < MAX_DRIVES; ++unit) {
|
||||
ide_drive_t *drive = &hwif->drives[unit];
|
||||
|
@ -968,11 +963,6 @@ static int ide_init_queue(ide_drive_t *drive)
|
|||
* Much of the code is for correctly detecting/handling irq sharing
|
||||
* and irq serialization situations. This is somewhat complex because
|
||||
* it handles static as well as dynamic (PCMCIA) IDE interfaces.
|
||||
*
|
||||
* The IRQF_DISABLED in sa_flags means ide_intr() is always entered with
|
||||
* interrupts completely disabled. This can be bad for interrupt latency,
|
||||
* but anything else has led to problems on some machines. We re-enable
|
||||
* interrupts as much as we can safely do in most places.
|
||||
*/
|
||||
static int init_irq (ide_hwif_t *hwif)
|
||||
{
|
||||
|
@ -1055,17 +1045,13 @@ static int init_irq (ide_hwif_t *hwif)
|
|||
* Allocate the irq, if not already obtained for another hwif
|
||||
*/
|
||||
if (!match || match->irq != hwif->irq) {
|
||||
int sa = IRQF_DISABLED;
|
||||
int sa = 0;
|
||||
#if defined(__mc68000__) || defined(CONFIG_APUS)
|
||||
sa = IRQF_SHARED;
|
||||
#endif /* __mc68000__ || CONFIG_APUS */
|
||||
|
||||
if (IDE_CHIPSET_IS_PCI(hwif->chipset)) {
|
||||
if (IDE_CHIPSET_IS_PCI(hwif->chipset))
|
||||
sa = IRQF_SHARED;
|
||||
#ifndef CONFIG_IDEPCI_SHARE_IRQ
|
||||
sa |= IRQF_DISABLED;
|
||||
#endif /* CONFIG_IDEPCI_SHARE_IRQ */
|
||||
}
|
||||
|
||||
if (hwif->io_ports[IDE_CONTROL_OFFSET])
|
||||
/* clear nIEN */
|
||||
|
|
|
@ -614,16 +614,6 @@ typedef struct os_dat_s {
|
|||
|
||||
/*************************** End of tunable parameters ***********************/
|
||||
|
||||
/*
|
||||
* Debugging/Performance analysis
|
||||
*
|
||||
* I/O trace support
|
||||
*/
|
||||
#define USE_IOTRACE 0
|
||||
#if USE_IOTRACE
|
||||
#define IO_IDETAPE_FIFO 500
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read/Write error simulation
|
||||
*/
|
||||
|
@ -1818,9 +1808,8 @@ static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
|
|||
idetape_tape_t *tape = drive->driver_data;
|
||||
idetape_pc_t *pc;
|
||||
struct request *rq;
|
||||
atapi_error_t error;
|
||||
|
||||
error.all = HWIF(drive)->INB(IDE_ERROR_REG);
|
||||
(void)drive->hwif->INB(IDE_ERROR_REG);
|
||||
pc = idetape_next_pc_storage(drive);
|
||||
rq = idetape_next_rq_storage(drive);
|
||||
idetape_create_request_sense_cmd(pc);
|
||||
|
@ -1858,15 +1847,13 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
|
|||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
idetape_tape_t *tape = drive->driver_data;
|
||||
atapi_status_t status;
|
||||
atapi_bcount_t bcount;
|
||||
atapi_ireason_t ireason;
|
||||
idetape_pc_t *pc = tape->pc;
|
||||
|
||||
unsigned int temp;
|
||||
#if SIMULATE_ERRORS
|
||||
static int error_sim_count = 0;
|
||||
#endif
|
||||
u16 bcount;
|
||||
u8 stat, ireason;
|
||||
|
||||
#if IDETAPE_DEBUG_LOG
|
||||
if (tape->debug_level >= 4)
|
||||
|
@ -1875,10 +1862,10 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
|
|||
#endif /* IDETAPE_DEBUG_LOG */
|
||||
|
||||
/* Clear the interrupt */
|
||||
status.all = HWIF(drive)->INB(IDE_STATUS_REG);
|
||||
stat = hwif->INB(IDE_STATUS_REG);
|
||||
|
||||
if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
|
||||
if (HWIF(drive)->ide_dma_end(drive) || status.b.check) {
|
||||
if (hwif->ide_dma_end(drive) || (stat & ERR_STAT)) {
|
||||
/*
|
||||
* A DMA error is sometimes expected. For example,
|
||||
* if the tape is crossing a filemark during a
|
||||
|
@ -1912,7 +1899,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
|
|||
}
|
||||
|
||||
/* No more interrupts */
|
||||
if (!status.b.drq) {
|
||||
if ((stat & DRQ_STAT) == 0) {
|
||||
#if IDETAPE_DEBUG_LOG
|
||||
if (tape->debug_level >= 2)
|
||||
printk(KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred);
|
||||
|
@ -1927,12 +1914,13 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
|
|||
(++error_sim_count % 100) == 0) {
|
||||
printk(KERN_INFO "ide-tape: %s: simulating error\n",
|
||||
tape->name);
|
||||
status.b.check = 1;
|
||||
stat |= ERR_STAT;
|
||||
}
|
||||
#endif
|
||||
if (status.b.check && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD)
|
||||
status.b.check = 0;
|
||||
if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) { /* Error detected */
|
||||
if ((stat & ERR_STAT) && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD)
|
||||
stat &= ~ERR_STAT;
|
||||
if ((stat & ERR_STAT) || test_bit(PC_DMA_ERROR, &pc->flags)) {
|
||||
/* Error detected */
|
||||
#if IDETAPE_DEBUG_LOG
|
||||
if (tape->debug_level >= 1)
|
||||
printk(KERN_INFO "ide-tape: %s: I/O error\n",
|
||||
|
@ -1951,7 +1939,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
|
|||
}
|
||||
pc->error = 0;
|
||||
if (test_bit(PC_WAIT_FOR_DSC, &pc->flags) &&
|
||||
!status.b.dsc) {
|
||||
(stat & SEEK_STAT) == 0) {
|
||||
/* Media access command */
|
||||
tape->dsc_polling_start = jiffies;
|
||||
tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST;
|
||||
|
@ -1973,30 +1961,30 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
|
|||
return ide_do_reset(drive);
|
||||
}
|
||||
/* Get the number of bytes to transfer on this interrupt. */
|
||||
bcount.b.high = hwif->INB(IDE_BCOUNTH_REG);
|
||||
bcount.b.low = hwif->INB(IDE_BCOUNTL_REG);
|
||||
bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
|
||||
hwif->INB(IDE_BCOUNTL_REG);
|
||||
|
||||
ireason.all = hwif->INB(IDE_IREASON_REG);
|
||||
ireason = hwif->INB(IDE_IREASON_REG);
|
||||
|
||||
if (ireason.b.cod) {
|
||||
if (ireason & CD) {
|
||||
printk(KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n");
|
||||
return ide_do_reset(drive);
|
||||
}
|
||||
if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) {
|
||||
if (((ireason & IO) == IO) == test_bit(PC_WRITING, &pc->flags)) {
|
||||
/* Hopefully, we will never get here */
|
||||
printk(KERN_ERR "ide-tape: We wanted to %s, ",
|
||||
ireason.b.io ? "Write":"Read");
|
||||
(ireason & IO) ? "Write" : "Read");
|
||||
printk(KERN_ERR "ide-tape: but the tape wants us to %s !\n",
|
||||
ireason.b.io ? "Read":"Write");
|
||||
(ireason & IO) ? "Read" : "Write");
|
||||
return ide_do_reset(drive);
|
||||
}
|
||||
if (!test_bit(PC_WRITING, &pc->flags)) {
|
||||
/* Reading - Check that we have enough space */
|
||||
temp = pc->actually_transferred + bcount.all;
|
||||
temp = pc->actually_transferred + bcount;
|
||||
if (temp > pc->request_transfer) {
|
||||
if (temp > pc->buffer_size) {
|
||||
printk(KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
|
||||
idetape_discard_data(drive, bcount.all);
|
||||
idetape_discard_data(drive, bcount);
|
||||
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
|
||||
return ide_started;
|
||||
}
|
||||
|
@ -2008,23 +1996,26 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
|
|||
}
|
||||
if (test_bit(PC_WRITING, &pc->flags)) {
|
||||
if (pc->bh != NULL)
|
||||
idetape_output_buffers(drive, pc, bcount.all);
|
||||
idetape_output_buffers(drive, pc, bcount);
|
||||
else
|
||||
/* Write the current buffer */
|
||||
HWIF(drive)->atapi_output_bytes(drive, pc->current_position, bcount.all);
|
||||
hwif->atapi_output_bytes(drive, pc->current_position,
|
||||
bcount);
|
||||
} else {
|
||||
if (pc->bh != NULL)
|
||||
idetape_input_buffers(drive, pc, bcount.all);
|
||||
idetape_input_buffers(drive, pc, bcount);
|
||||
else
|
||||
/* Read the current buffer */
|
||||
HWIF(drive)->atapi_input_bytes(drive, pc->current_position, bcount.all);
|
||||
hwif->atapi_input_bytes(drive, pc->current_position,
|
||||
bcount);
|
||||
}
|
||||
/* Update the current position */
|
||||
pc->actually_transferred += bcount.all;
|
||||
pc->current_position += bcount.all;
|
||||
pc->actually_transferred += bcount;
|
||||
pc->current_position += bcount;
|
||||
#if IDETAPE_DEBUG_LOG
|
||||
if (tape->debug_level >= 2)
|
||||
printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
|
||||
printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes "
|
||||
"on that interrupt\n", pc->c[0], bcount);
|
||||
#endif
|
||||
/* And set the interrupt handler again */
|
||||
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
|
||||
|
@ -2078,28 +2069,28 @@ 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_pc_t *pc = tape->pc;
|
||||
atapi_ireason_t ireason;
|
||||
int retries = 100;
|
||||
ide_startstop_t startstop;
|
||||
u8 ireason;
|
||||
|
||||
if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
|
||||
printk(KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
|
||||
return startstop;
|
||||
}
|
||||
ireason.all = hwif->INB(IDE_IREASON_REG);
|
||||
while (retries-- && (!ireason.b.cod || ireason.b.io)) {
|
||||
ireason = hwif->INB(IDE_IREASON_REG);
|
||||
while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
|
||||
printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing "
|
||||
"a packet command, retrying\n");
|
||||
udelay(100);
|
||||
ireason.all = hwif->INB(IDE_IREASON_REG);
|
||||
ireason = hwif->INB(IDE_IREASON_REG);
|
||||
if (retries == 0) {
|
||||
printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while "
|
||||
"issuing a packet command, ignoring\n");
|
||||
ireason.b.cod = 1;
|
||||
ireason.b.io = 0;
|
||||
ireason |= CD;
|
||||
ireason &= ~IO;
|
||||
}
|
||||
}
|
||||
if (!ireason.b.cod || ireason.b.io) {
|
||||
if ((ireason & CD) == 0 || (ireason & IO)) {
|
||||
printk(KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing "
|
||||
"a packet command\n");
|
||||
return ide_do_reset(drive);
|
||||
|
@ -2120,8 +2111,8 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
|
|||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
idetape_tape_t *tape = drive->driver_data;
|
||||
atapi_bcount_t bcount;
|
||||
int dma_ok = 0;
|
||||
u16 bcount;
|
||||
|
||||
#if IDETAPE_DEBUG_BUGS
|
||||
if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD &&
|
||||
|
@ -2170,7 +2161,7 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
|
|||
pc->actually_transferred = 0;
|
||||
pc->current_position = pc->buffer;
|
||||
/* Request to transfer the entire buffer at once */
|
||||
bcount.all = pc->request_transfer;
|
||||
bcount = pc->request_transfer;
|
||||
|
||||
if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
|
||||
printk(KERN_WARNING "ide-tape: DMA disabled, "
|
||||
|
@ -2180,12 +2171,9 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
|
|||
if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
|
||||
dma_ok = !hwif->dma_setup(drive);
|
||||
|
||||
if (IDE_CONTROL_REG)
|
||||
hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
|
||||
hwif->OUTB(dma_ok ? 1 : 0, IDE_FEATURE_REG); /* Use PIO/DMA */
|
||||
hwif->OUTB(bcount.b.high, IDE_BCOUNTH_REG);
|
||||
hwif->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
|
||||
hwif->OUTB(drive->select.all, IDE_SELECT_REG);
|
||||
ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
|
||||
IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
|
||||
|
||||
if (dma_ok) /* Will begin DMA later */
|
||||
set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
|
||||
if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
|
||||
|
@ -2295,11 +2283,11 @@ static ide_startstop_t idetape_media_access_finished (ide_drive_t *drive)
|
|||
{
|
||||
idetape_tape_t *tape = drive->driver_data;
|
||||
idetape_pc_t *pc = tape->pc;
|
||||
atapi_status_t status;
|
||||
u8 stat;
|
||||
|
||||
status.all = HWIF(drive)->INB(IDE_STATUS_REG);
|
||||
if (status.b.dsc) {
|
||||
if (status.b.check) {
|
||||
stat = drive->hwif->INB(IDE_STATUS_REG);
|
||||
if (stat & SEEK_STAT) {
|
||||
if (stat & ERR_STAT) {
|
||||
/* Error detected */
|
||||
if (pc->c[0] != IDETAPE_TEST_UNIT_READY_CMD)
|
||||
printk(KERN_ERR "ide-tape: %s: I/O error, ",
|
||||
|
@ -2417,7 +2405,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
|
|||
idetape_tape_t *tape = drive->driver_data;
|
||||
idetape_pc_t *pc = NULL;
|
||||
struct request *postponed_rq = tape->postponed_rq;
|
||||
atapi_status_t status;
|
||||
u8 stat;
|
||||
|
||||
#if IDETAPE_DEBUG_LOG
|
||||
#if 0
|
||||
|
@ -2465,7 +2453,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
|
|||
* If the tape is still busy, postpone our request and service
|
||||
* the other device meanwhile.
|
||||
*/
|
||||
status.all = HWIF(drive)->INB(IDE_STATUS_REG);
|
||||
stat = drive->hwif->INB(IDE_STATUS_REG);
|
||||
|
||||
if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
|
||||
set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
|
||||
|
@ -2481,7 +2469,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
|
|||
tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
|
||||
calculate_speeds(drive);
|
||||
if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) &&
|
||||
!status.b.dsc) {
|
||||
(stat & SEEK_STAT) == 0) {
|
||||
if (postponed_rq == NULL) {
|
||||
tape->dsc_polling_start = jiffies;
|
||||
tape->dsc_polling_frequency = tape->best_dsc_rw_frequency;
|
||||
|
@ -2502,9 +2490,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
|
|||
}
|
||||
if (rq->cmd[0] & REQ_IDETAPE_READ) {
|
||||
tape->buffer_head++;
|
||||
#if USE_IOTRACE
|
||||
IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
|
||||
#endif
|
||||
tape->postpone_cnt = 0;
|
||||
pc = idetape_next_pc_storage(drive);
|
||||
idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
|
||||
|
@ -2512,9 +2497,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
|
|||
}
|
||||
if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
|
||||
tape->buffer_head++;
|
||||
#if USE_IOTRACE
|
||||
IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
|
||||
#endif
|
||||
tape->postpone_cnt = 0;
|
||||
pc = idetape_next_pc_storage(drive);
|
||||
idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
|
||||
|
@ -3241,9 +3223,6 @@ static int idetape_add_chrdev_write_request (ide_drive_t *drive, int blocks)
|
|||
idetape_switch_buffers(tape, new_stage);
|
||||
idetape_add_stage_tail(drive, new_stage);
|
||||
tape->pipeline_head++;
|
||||
#if USE_IOTRACE
|
||||
IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
|
||||
#endif
|
||||
calculate_speeds(drive);
|
||||
|
||||
/*
|
||||
|
@ -3493,9 +3472,6 @@ static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks)
|
|||
idetape_remove_stage_head(drive);
|
||||
spin_unlock_irqrestore(&tape->spinlock, flags);
|
||||
tape->pipeline_head++;
|
||||
#if USE_IOTRACE
|
||||
IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
|
||||
#endif
|
||||
calculate_speeds(drive);
|
||||
}
|
||||
#if IDETAPE_DEBUG_BUGS
|
||||
|
|
|
@ -63,65 +63,78 @@ static void taskfile_output_data(ide_drive_t *drive, void *buffer, u32 wcount)
|
|||
}
|
||||
}
|
||||
|
||||
void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct ide_taskfile *tf = &task->tf;
|
||||
u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_FLAGGED)
|
||||
HIHI = 0xFF;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x "
|
||||
"lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n",
|
||||
drive->name, tf->feature, tf->nsect, tf->lbal,
|
||||
tf->lbam, tf->lbah, tf->device, tf->command);
|
||||
#endif
|
||||
|
||||
if (IDE_CONTROL_REG)
|
||||
hwif->OUTB(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
|
||||
|
||||
if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
|
||||
SELECT_MASK(drive, 0);
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_DATA)
|
||||
hwif->OUTW((tf->hob_data << 8) | tf->data, IDE_DATA_REG);
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
|
||||
hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
|
||||
hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
|
||||
hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
|
||||
hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
|
||||
hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG);
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
|
||||
hwif->OUTB(tf->feature, IDE_FEATURE_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
|
||||
hwif->OUTB(tf->nsect, IDE_NSECTOR_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
|
||||
hwif->OUTB(tf->lbal, IDE_SECTOR_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
|
||||
hwif->OUTB(tf->lbam, IDE_LCYL_REG);
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
|
||||
hwif->OUTB(tf->lbah, IDE_HCYL_REG);
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
|
||||
hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG);
|
||||
}
|
||||
|
||||
int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
|
||||
{
|
||||
ide_task_t args;
|
||||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01;
|
||||
args.tf.nsect = 0x01;
|
||||
if (drive->media == ide_disk)
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_IDENTIFY;
|
||||
args.tf.command = WIN_IDENTIFY;
|
||||
else
|
||||
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_PIDENTIFY;
|
||||
args.command_type = IDE_DRIVE_TASK_IN;
|
||||
args.tf.command = WIN_PIDENTIFY;
|
||||
args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
args.data_phase = TASKFILE_IN;
|
||||
args.handler = &task_in_intr;
|
||||
return ide_raw_taskfile(drive, &args, buf);
|
||||
return ide_raw_taskfile(drive, &args, buf, 1);
|
||||
}
|
||||
|
||||
ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
|
||||
static int inline task_dma_ok(ide_task_t *task)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
|
||||
hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
|
||||
u8 HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF;
|
||||
if (blk_fs_request(task->rq) || (task->tf_flags & IDE_TFLAG_FLAGGED))
|
||||
return 1;
|
||||
|
||||
/* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
|
||||
if (IDE_CONTROL_REG) {
|
||||
/* clear nIEN */
|
||||
hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
|
||||
}
|
||||
SELECT_MASK(drive, 0);
|
||||
|
||||
if (drive->addressing == 1) {
|
||||
hwif->OUTB(hobfile->feature, IDE_FEATURE_REG);
|
||||
hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
|
||||
hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
|
||||
hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
|
||||
hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
|
||||
}
|
||||
|
||||
hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
|
||||
hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
|
||||
hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
|
||||
hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
|
||||
hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
|
||||
|
||||
hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
|
||||
|
||||
if (task->handler != NULL) {
|
||||
if (task->prehandler != NULL) {
|
||||
hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
|
||||
ndelay(400); /* FIXME */
|
||||
return task->prehandler(drive, task->rq);
|
||||
}
|
||||
ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
|
||||
return ide_started;
|
||||
}
|
||||
|
||||
if (!drive->using_dma)
|
||||
return ide_stopped;
|
||||
|
||||
switch (taskfile->command) {
|
||||
switch (task->tf.command) {
|
||||
case WIN_WRITEDMA_ONCE:
|
||||
case WIN_WRITEDMA:
|
||||
case WIN_WRITEDMA_EXT:
|
||||
|
@ -129,24 +142,79 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
|
|||
case WIN_READDMA:
|
||||
case WIN_READDMA_EXT:
|
||||
case WIN_IDENTIFY_DMA:
|
||||
if (!hwif->dma_setup(drive)) {
|
||||
hwif->dma_exec_cmd(drive, taskfile->command);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ide_startstop_t task_no_data_intr(ide_drive_t *);
|
||||
static ide_startstop_t set_geometry_intr(ide_drive_t *);
|
||||
static ide_startstop_t recal_intr(ide_drive_t *);
|
||||
static ide_startstop_t set_multmode_intr(ide_drive_t *);
|
||||
static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
|
||||
static ide_startstop_t task_in_intr(ide_drive_t *);
|
||||
|
||||
ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct ide_taskfile *tf = &task->tf;
|
||||
ide_handler_t *handler = NULL;
|
||||
|
||||
if (task->data_phase == TASKFILE_MULTI_IN ||
|
||||
task->data_phase == TASKFILE_MULTI_OUT) {
|
||||
if (!drive->mult_count) {
|
||||
printk(KERN_ERR "%s: multimode not set!\n",
|
||||
drive->name);
|
||||
return ide_stopped;
|
||||
}
|
||||
}
|
||||
|
||||
if (task->tf_flags & IDE_TFLAG_FLAGGED)
|
||||
task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
|
||||
|
||||
if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0)
|
||||
ide_tf_load(drive, task);
|
||||
|
||||
switch (task->data_phase) {
|
||||
case TASKFILE_MULTI_OUT:
|
||||
case TASKFILE_OUT:
|
||||
hwif->OUTBSYNC(drive, tf->command, IDE_COMMAND_REG);
|
||||
ndelay(400); /* FIXME */
|
||||
return pre_task_out_intr(drive, task->rq);
|
||||
case TASKFILE_MULTI_IN:
|
||||
case TASKFILE_IN:
|
||||
handler = task_in_intr;
|
||||
/* fall-through */
|
||||
case TASKFILE_NO_DATA:
|
||||
if (handler == NULL)
|
||||
handler = task_no_data_intr;
|
||||
/* WIN_{SPECIFY,RESTORE,SETMULT} use custom handlers */
|
||||
if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) {
|
||||
switch (tf->command) {
|
||||
case WIN_SPECIFY: handler = set_geometry_intr; break;
|
||||
case WIN_RESTORE: handler = recal_intr; break;
|
||||
case WIN_SETMULT: handler = set_multmode_intr; break;
|
||||
}
|
||||
}
|
||||
ide_execute_command(drive, tf->command, handler,
|
||||
WAIT_WORSTCASE, NULL);
|
||||
return ide_started;
|
||||
default:
|
||||
if (task_dma_ok(task) == 0 || drive->using_dma == 0 ||
|
||||
hwif->dma_setup(drive))
|
||||
return ide_stopped;
|
||||
hwif->dma_exec_cmd(drive, tf->command);
|
||||
hwif->dma_start(drive);
|
||||
return ide_started;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (task->handler == NULL)
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
return ide_stopped;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(do_rw_taskfile);
|
||||
|
||||
/*
|
||||
* set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
|
||||
*/
|
||||
ide_startstop_t set_multmode_intr (ide_drive_t *drive)
|
||||
static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
u8 stat;
|
||||
|
@ -164,7 +232,7 @@ ide_startstop_t set_multmode_intr (ide_drive_t *drive)
|
|||
/*
|
||||
* set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
|
||||
*/
|
||||
ide_startstop_t set_geometry_intr (ide_drive_t *drive)
|
||||
static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
int retries = 5;
|
||||
|
@ -187,7 +255,7 @@ ide_startstop_t set_geometry_intr (ide_drive_t *drive)
|
|||
/*
|
||||
* recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
|
||||
*/
|
||||
ide_startstop_t recal_intr (ide_drive_t *drive)
|
||||
static ide_startstop_t recal_intr(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
u8 stat;
|
||||
|
@ -200,7 +268,7 @@ ide_startstop_t recal_intr (ide_drive_t *drive)
|
|||
/*
|
||||
* Handler for commands without a data phase
|
||||
*/
|
||||
ide_startstop_t task_no_data_intr (ide_drive_t *drive)
|
||||
static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
|
||||
{
|
||||
ide_task_t *args = HWGROUP(drive)->rq->special;
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
|
@ -217,8 +285,6 @@ ide_startstop_t task_no_data_intr (ide_drive_t *drive)
|
|||
return ide_stopped;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(task_no_data_intr);
|
||||
|
||||
static u8 wait_drive_not_busy(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
|
@ -363,7 +429,7 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
|
|||
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
|
||||
ide_task_t *task = rq->special;
|
||||
|
||||
if (task->tf_out_flags.all) {
|
||||
if (task->tf_flags & IDE_TFLAG_FLAGGED) {
|
||||
u8 err = drive->hwif->INB(IDE_ERROR_REG);
|
||||
ide_end_drive_cmd(drive, stat, err);
|
||||
return;
|
||||
|
@ -382,7 +448,7 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
|
|||
/*
|
||||
* Handler for command with PIO data-in phase (Read/Read Multiple).
|
||||
*/
|
||||
ide_startstop_t task_in_intr (ide_drive_t *drive)
|
||||
static ide_startstop_t task_in_intr(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct request *rq = HWGROUP(drive)->rq;
|
||||
|
@ -413,7 +479,6 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
|
|||
|
||||
return ide_started;
|
||||
}
|
||||
EXPORT_SYMBOL(task_in_intr);
|
||||
|
||||
/*
|
||||
* Handler for command with PIO data-out phase (Write/Write Multiple).
|
||||
|
@ -443,7 +508,7 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
|
|||
return ide_started;
|
||||
}
|
||||
|
||||
ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
|
||||
static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
ide_startstop_t startstop;
|
||||
|
||||
|
@ -464,9 +529,8 @@ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
|
|||
|
||||
return ide_started;
|
||||
}
|
||||
EXPORT_SYMBOL(pre_task_out_intr);
|
||||
|
||||
static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
|
||||
int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
|
||||
{
|
||||
struct request rq;
|
||||
|
||||
|
@ -481,37 +545,28 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long
|
|||
* if we would find a solution to transfer any size.
|
||||
* To support special commands like READ LONG.
|
||||
*/
|
||||
if (args->command_type != IDE_DRIVE_TASK_NO_DATA) {
|
||||
if (data_size == 0)
|
||||
rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET];
|
||||
else
|
||||
rq.nr_sectors = data_size / SECTOR_SIZE;
|
||||
rq.hard_nr_sectors = rq.nr_sectors = nsect;
|
||||
rq.hard_cur_sectors = rq.current_nr_sectors = nsect;
|
||||
|
||||
if (!rq.nr_sectors) {
|
||||
printk(KERN_ERR "%s: in/out command without data\n",
|
||||
drive->name);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
rq.hard_nr_sectors = rq.nr_sectors;
|
||||
rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors;
|
||||
|
||||
if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
|
||||
if (task->tf_flags & IDE_TFLAG_WRITE)
|
||||
rq.cmd_flags |= REQ_RW;
|
||||
}
|
||||
|
||||
rq.special = args;
|
||||
args->rq = &rq;
|
||||
rq.special = task;
|
||||
task->rq = &rq;
|
||||
|
||||
return ide_do_drive_cmd(drive, &rq, ide_wait);
|
||||
}
|
||||
|
||||
int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf)
|
||||
{
|
||||
return ide_diag_taskfile(drive, args, 0, buf);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_raw_taskfile);
|
||||
|
||||
int ide_no_data_taskfile(ide_drive_t *drive, ide_task_t *task)
|
||||
{
|
||||
task->data_phase = TASKFILE_NO_DATA;
|
||||
|
||||
return ide_raw_taskfile(drive, task, NULL, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_no_data_taskfile);
|
||||
|
||||
#ifdef CONFIG_IDE_TASK_IOCTL
|
||||
int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
|
@ -519,12 +574,12 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
|
|||
ide_task_t args;
|
||||
u8 *outbuf = NULL;
|
||||
u8 *inbuf = NULL;
|
||||
task_ioreg_t *argsptr = args.tfRegister;
|
||||
task_ioreg_t *hobsptr = args.hobRegister;
|
||||
u8 *data_buf = NULL;
|
||||
int err = 0;
|
||||
int tasksize = sizeof(struct ide_task_request_s);
|
||||
unsigned int taskin = 0;
|
||||
unsigned int taskout = 0;
|
||||
u16 nsect = 0;
|
||||
u8 io_32bit = drive->io_32bit;
|
||||
char __user *buf = (char __user *)arg;
|
||||
|
||||
|
@ -572,24 +627,52 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
|
|||
}
|
||||
|
||||
memset(&args, 0, sizeof(ide_task_t));
|
||||
memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
|
||||
memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE);
|
||||
|
||||
args.tf_in_flags = req_task->in_flags;
|
||||
args.tf_out_flags = req_task->out_flags;
|
||||
memcpy(&args.tf_array[0], req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2);
|
||||
memcpy(&args.tf_array[6], req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
|
||||
|
||||
args.data_phase = req_task->data_phase;
|
||||
args.command_type = req_task->req_cmd;
|
||||
|
||||
args.tf_flags = IDE_TFLAG_OUT_DEVICE;
|
||||
if (drive->addressing == 1)
|
||||
args.tf_flags |= IDE_TFLAG_LBA48;
|
||||
|
||||
if (req_task->out_flags.all) {
|
||||
args.tf_flags |= IDE_TFLAG_FLAGGED;
|
||||
|
||||
if (req_task->out_flags.b.data)
|
||||
args.tf_flags |= IDE_TFLAG_OUT_DATA;
|
||||
|
||||
if (req_task->out_flags.b.nsector_hob)
|
||||
args.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT;
|
||||
if (req_task->out_flags.b.sector_hob)
|
||||
args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL;
|
||||
if (req_task->out_flags.b.lcyl_hob)
|
||||
args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM;
|
||||
if (req_task->out_flags.b.hcyl_hob)
|
||||
args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH;
|
||||
|
||||
if (req_task->out_flags.b.error_feature)
|
||||
args.tf_flags |= IDE_TFLAG_OUT_FEATURE;
|
||||
if (req_task->out_flags.b.nsector)
|
||||
args.tf_flags |= IDE_TFLAG_OUT_NSECT;
|
||||
if (req_task->out_flags.b.sector)
|
||||
args.tf_flags |= IDE_TFLAG_OUT_LBAL;
|
||||
if (req_task->out_flags.b.lcyl)
|
||||
args.tf_flags |= IDE_TFLAG_OUT_LBAM;
|
||||
if (req_task->out_flags.b.hcyl)
|
||||
args.tf_flags |= IDE_TFLAG_OUT_LBAH;
|
||||
} else {
|
||||
args.tf_flags |= IDE_TFLAG_OUT_TF;
|
||||
if (args.tf_flags & IDE_TFLAG_LBA48)
|
||||
args.tf_flags |= IDE_TFLAG_OUT_HOB;
|
||||
}
|
||||
|
||||
if (req_task->in_flags.b.data)
|
||||
args.tf_flags |= IDE_TFLAG_IN_DATA;
|
||||
|
||||
drive->io_32bit = 0;
|
||||
switch(req_task->data_phase) {
|
||||
case TASKFILE_OUT_DMAQ:
|
||||
case TASKFILE_OUT_DMA:
|
||||
err = ide_diag_taskfile(drive, &args, taskout, outbuf);
|
||||
break;
|
||||
case TASKFILE_IN_DMAQ:
|
||||
case TASKFILE_IN_DMA:
|
||||
err = ide_diag_taskfile(drive, &args, taskin, inbuf);
|
||||
break;
|
||||
case TASKFILE_MULTI_OUT:
|
||||
if (!drive->mult_count) {
|
||||
/* (hs): give up if multcount is not set */
|
||||
|
@ -601,9 +684,11 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
|
|||
}
|
||||
/* fall through */
|
||||
case TASKFILE_OUT:
|
||||
args.prehandler = &pre_task_out_intr;
|
||||
args.handler = &task_out_intr;
|
||||
err = ide_diag_taskfile(drive, &args, taskout, outbuf);
|
||||
/* fall through */
|
||||
case TASKFILE_OUT_DMAQ:
|
||||
case TASKFILE_OUT_DMA:
|
||||
nsect = taskout / SECTOR_SIZE;
|
||||
data_buf = outbuf;
|
||||
break;
|
||||
case TASKFILE_MULTI_IN:
|
||||
if (!drive->mult_count) {
|
||||
|
@ -616,22 +701,46 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
|
|||
}
|
||||
/* fall through */
|
||||
case TASKFILE_IN:
|
||||
args.handler = &task_in_intr;
|
||||
err = ide_diag_taskfile(drive, &args, taskin, inbuf);
|
||||
/* fall through */
|
||||
case TASKFILE_IN_DMAQ:
|
||||
case TASKFILE_IN_DMA:
|
||||
nsect = taskin / SECTOR_SIZE;
|
||||
data_buf = inbuf;
|
||||
break;
|
||||
case TASKFILE_NO_DATA:
|
||||
args.handler = &task_no_data_intr;
|
||||
err = ide_diag_taskfile(drive, &args, 0, NULL);
|
||||
break;
|
||||
default:
|
||||
err = -EFAULT;
|
||||
goto abort;
|
||||
}
|
||||
|
||||
memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE);
|
||||
memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE);
|
||||
req_task->in_flags = args.tf_in_flags;
|
||||
req_task->out_flags = args.tf_out_flags;
|
||||
if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA)
|
||||
nsect = 0;
|
||||
else if (!nsect) {
|
||||
nsect = (args.tf.hob_nsect << 8) | args.tf.nsect;
|
||||
|
||||
if (!nsect) {
|
||||
printk(KERN_ERR "%s: in/out command without data\n",
|
||||
drive->name);
|
||||
err = -EFAULT;
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
|
||||
if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE)
|
||||
args.tf_flags |= IDE_TFLAG_WRITE;
|
||||
|
||||
err = ide_raw_taskfile(drive, &args, data_buf, nsect);
|
||||
|
||||
memcpy(req_task->hob_ports, &args.tf_array[0], HDIO_DRIVE_HOB_HDR_SIZE - 2);
|
||||
memcpy(req_task->io_ports, &args.tf_array[6], HDIO_DRIVE_TASK_HDR_SIZE);
|
||||
|
||||
if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) &&
|
||||
req_task->in_flags.all == 0) {
|
||||
req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
|
||||
if (drive->addressing == 1)
|
||||
req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
|
||||
}
|
||||
|
||||
if (copy_to_user(buf, req_task, tasksize)) {
|
||||
err = -EFAULT;
|
||||
|
@ -688,6 +797,7 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
|
|||
u8 xfer_rate = 0;
|
||||
int argsize = 4;
|
||||
ide_task_t tfargs;
|
||||
struct ide_taskfile *tf = &tfargs.tf;
|
||||
|
||||
if (NULL == (void *) arg) {
|
||||
struct request rq;
|
||||
|
@ -699,13 +809,10 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
|
|||
return -EFAULT;
|
||||
|
||||
memset(&tfargs, 0, sizeof(ide_task_t));
|
||||
tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2];
|
||||
tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3];
|
||||
tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1];
|
||||
tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00;
|
||||
tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00;
|
||||
tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00;
|
||||
tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0];
|
||||
tf->feature = args[2];
|
||||
tf->nsect = args[3];
|
||||
tf->lbal = args[1];
|
||||
tf->command = args[0];
|
||||
|
||||
if (args[3]) {
|
||||
argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
|
||||
|
@ -734,135 +841,28 @@ abort:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf)
|
||||
{
|
||||
struct request rq;
|
||||
|
||||
ide_init_drive_cmd(&rq);
|
||||
rq.cmd_type = REQ_TYPE_ATA_TASK;
|
||||
rq.buffer = buf;
|
||||
return ide_do_drive_cmd(drive, &rq, ide_wait);
|
||||
}
|
||||
|
||||
int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
void __user *p = (void __user *)arg;
|
||||
int err = 0;
|
||||
u8 args[7], *argbuf = args;
|
||||
int argsize = 7;
|
||||
u8 args[7];
|
||||
ide_task_t task;
|
||||
|
||||
if (copy_from_user(args, p, 7))
|
||||
return -EFAULT;
|
||||
err = ide_wait_cmd_task(drive, argbuf);
|
||||
if (copy_to_user(p, argbuf, argsize))
|
||||
|
||||
memset(&task, 0, sizeof(task));
|
||||
memcpy(&task.tf_array[7], &args[1], 6);
|
||||
task.tf.command = args[0];
|
||||
task.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
|
||||
|
||||
err = ide_no_data_taskfile(drive, &task);
|
||||
|
||||
args[0] = task.tf.command;
|
||||
memcpy(&args[1], &task.tf_array[7], 6);
|
||||
|
||||
if (copy_to_user(p, args, 7))
|
||||
err = -EFAULT;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTICE: This is additions from IBM to provide a discrete interface,
|
||||
* for selective taskregister access operations. Nice JOB Klaus!!!
|
||||
* Glad to be able to work and co-develop this with you and IBM.
|
||||
*/
|
||||
ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
|
||||
hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
|
||||
|
||||
if (task->data_phase == TASKFILE_MULTI_IN ||
|
||||
task->data_phase == TASKFILE_MULTI_OUT) {
|
||||
if (!drive->mult_count) {
|
||||
printk(KERN_ERR "%s: multimode not set!\n", drive->name);
|
||||
return ide_stopped;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (ks) Check taskfile in flags.
|
||||
* If set, then execute as it is defined.
|
||||
* If not set, then define default settings.
|
||||
* The default values are:
|
||||
* read all taskfile registers (except data)
|
||||
* read the hob registers (sector, nsector, lcyl, hcyl)
|
||||
*/
|
||||
if (task->tf_in_flags.all == 0) {
|
||||
task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
|
||||
if (drive->addressing == 1)
|
||||
task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
|
||||
}
|
||||
|
||||
/* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
|
||||
if (IDE_CONTROL_REG)
|
||||
/* clear nIEN */
|
||||
hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
|
||||
SELECT_MASK(drive, 0);
|
||||
|
||||
if (task->tf_out_flags.b.data) {
|
||||
u16 data = taskfile->data + (hobfile->data << 8);
|
||||
hwif->OUTW(data, IDE_DATA_REG);
|
||||
}
|
||||
|
||||
/* (ks) send hob registers first */
|
||||
if (task->tf_out_flags.b.nsector_hob)
|
||||
hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
|
||||
if (task->tf_out_flags.b.sector_hob)
|
||||
hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
|
||||
if (task->tf_out_flags.b.lcyl_hob)
|
||||
hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
|
||||
if (task->tf_out_flags.b.hcyl_hob)
|
||||
hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
|
||||
|
||||
/* (ks) Send now the standard registers */
|
||||
if (task->tf_out_flags.b.error_feature)
|
||||
hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
|
||||
/* refers to number of sectors to transfer */
|
||||
if (task->tf_out_flags.b.nsector)
|
||||
hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
|
||||
/* refers to sector offset or start sector */
|
||||
if (task->tf_out_flags.b.sector)
|
||||
hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
|
||||
if (task->tf_out_flags.b.lcyl)
|
||||
hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
|
||||
if (task->tf_out_flags.b.hcyl)
|
||||
hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
|
||||
|
||||
/*
|
||||
* (ks) In the flagged taskfile approch, we will use all specified
|
||||
* registers and the register value will not be changed, except the
|
||||
* select bit (master/slave) in the drive_head register. We must make
|
||||
* sure that the desired drive is selected.
|
||||
*/
|
||||
hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG);
|
||||
switch(task->data_phase) {
|
||||
|
||||
case TASKFILE_OUT_DMAQ:
|
||||
case TASKFILE_OUT_DMA:
|
||||
case TASKFILE_IN_DMAQ:
|
||||
case TASKFILE_IN_DMA:
|
||||
if (!drive->using_dma)
|
||||
break;
|
||||
|
||||
if (!hwif->dma_setup(drive)) {
|
||||
hwif->dma_exec_cmd(drive, taskfile->command);
|
||||
hwif->dma_start(drive);
|
||||
return ide_started;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (task->handler == NULL)
|
||||
return ide_stopped;
|
||||
|
||||
/* Issue the command */
|
||||
if (task->prehandler) {
|
||||
hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
|
||||
ndelay(400); /* FIXME */
|
||||
return task->prehandler(drive, task->rq);
|
||||
}
|
||||
ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
|
||||
return ide_started;
|
||||
}
|
||||
|
||||
return ide_stopped;
|
||||
}
|
||||
|
|
|
@ -424,7 +424,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
|
|||
hwif->reset_poll = tmp_hwif->reset_poll;
|
||||
hwif->pre_reset = tmp_hwif->pre_reset;
|
||||
hwif->resetproc = tmp_hwif->resetproc;
|
||||
hwif->intrproc = tmp_hwif->intrproc;
|
||||
hwif->maskproc = tmp_hwif->maskproc;
|
||||
hwif->quirkproc = tmp_hwif->quirkproc;
|
||||
hwif->busproc = tmp_hwif->busproc;
|
||||
|
@ -468,7 +467,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
|
|||
#endif
|
||||
|
||||
hwif->dma_base = tmp_hwif->dma_base;
|
||||
hwif->dma_master = tmp_hwif->dma_master;
|
||||
hwif->dma_command = tmp_hwif->dma_command;
|
||||
hwif->dma_vendor1 = tmp_hwif->dma_vendor1;
|
||||
hwif->dma_status = tmp_hwif->dma_status;
|
||||
|
@ -602,7 +600,6 @@ void ide_unregister(unsigned int index)
|
|||
(void) ide_release_dma(hwif);
|
||||
|
||||
hwif->dma_base = 0;
|
||||
hwif->dma_master = 0;
|
||||
hwif->dma_command = 0;
|
||||
hwif->dma_vendor1 = 0;
|
||||
hwif->dma_status = 0;
|
||||
|
@ -854,8 +851,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
|
|||
err = 0;
|
||||
|
||||
if (arg) {
|
||||
hwif->dma_off_quietly(drive);
|
||||
if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
|
||||
if (ide_set_dma(drive))
|
||||
err = -EIO;
|
||||
} else
|
||||
ide_dma_off(drive);
|
||||
|
|
|
@ -198,8 +198,6 @@ static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
au_writel(mem_sttime,MEM_STTIME2);
|
||||
|
|
|
@ -202,6 +202,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
|
|||
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
|
||||
.host_flags = IDE_HFLAG_SERIALIZE |
|
||||
IDE_HFLAG_NO_ATAPI_DMA |
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE |
|
||||
IDE_HFLAG_OFF_BOARD,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
|
@ -211,6 +212,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
|
|||
.init_chipset = init_chipset_aec62xx,
|
||||
.init_hwif = init_hwif_aec62xx,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE |
|
||||
IDE_HFLAG_OFF_BOARD,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
|
@ -220,7 +222,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
|
|||
.init_chipset = init_chipset_aec62xx,
|
||||
.init_hwif = init_hwif_aec62xx,
|
||||
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = ATA_UDMA4,
|
||||
|
@ -228,7 +231,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
|
|||
.name = "AEC6280",
|
||||
.init_chipset = init_chipset_aec62xx,
|
||||
.init_hwif = init_hwif_aec62xx,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE |
|
||||
IDE_HFLAG_OFF_BOARD,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = ATA_UDMA5,
|
||||
|
@ -237,7 +242,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
|
|||
.init_chipset = init_chipset_aec62xx,
|
||||
.init_hwif = init_hwif_aec62xx,
|
||||
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE |
|
||||
IDE_HFLAG_OFF_BOARD,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = ATA_UDMA5,
|
||||
|
|
|
@ -402,9 +402,6 @@ static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
u8 tmpbyte = 0x00;
|
||||
int m5229_udma = (hwif->channel) ? 0x57 : 0x56;
|
||||
|
||||
if (speed < XFER_PIO_0)
|
||||
return;
|
||||
|
||||
if (speed == XFER_UDMA_6)
|
||||
speed1 = 0x47;
|
||||
|
||||
|
|
|
@ -266,6 +266,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
|
|||
#define IDE_HFLAGS_AMD \
|
||||
(IDE_HFLAG_PIO_NO_BLACKLIST | \
|
||||
IDE_HFLAG_PIO_NO_DOWNGRADE | \
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE | \
|
||||
IDE_HFLAG_POST_SET_MODE | \
|
||||
IDE_HFLAG_IO_32BIT | \
|
||||
IDE_HFLAG_UNMASK_IRQS | \
|
||||
|
|
|
@ -133,9 +133,6 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
u32 tmp32;
|
||||
u16 tmp16;
|
||||
|
||||
if (speed < XFER_MW_DMA_0)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&atiixp_lock, flags);
|
||||
|
||||
save_mdma_mode[drive->dn] = 0;
|
||||
|
|
|
@ -322,8 +322,6 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
case XFER_MW_DMA_0:
|
||||
program_cycle_times(drive, 480, 215);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (speed >= XFER_SW_DMA_0)
|
||||
|
@ -333,14 +331,15 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
static int cmd648_ide_dma_end (ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
unsigned long base = hwif->dma_base - (hwif->channel * 8);
|
||||
int err = __ide_dma_end(drive);
|
||||
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
|
||||
MRDMODE_INTR_CH0;
|
||||
u8 mrdmode = inb(hwif->dma_master + 0x01);
|
||||
u8 mrdmode = inb(base + 1);
|
||||
|
||||
/* clear the interrupt bit */
|
||||
outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
|
||||
hwif->dma_master + 0x01);
|
||||
base + 1);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -365,10 +364,11 @@ static int cmd64x_ide_dma_end (ide_drive_t *drive)
|
|||
static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
unsigned long base = hwif->dma_base - (hwif->channel * 8);
|
||||
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
|
||||
MRDMODE_INTR_CH0;
|
||||
u8 dma_stat = inb(hwif->dma_status);
|
||||
u8 mrdmode = inb(hwif->dma_master + 0x01);
|
||||
u8 mrdmode = inb(base + 1);
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
|
||||
|
|
|
@ -137,6 +137,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
|
|||
IDE_HFLAG_CS5520 | \
|
||||
IDE_HFLAG_VDMA | \
|
||||
IDE_HFLAG_NO_ATAPI_DMA | \
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE |\
|
||||
IDE_HFLAG_BOOTABLE, \
|
||||
.pio_mask = ATA_PIO4, \
|
||||
}
|
||||
|
|
|
@ -116,8 +116,6 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
|||
case XFER_MW_DMA_0: timings = 0x00077771; break;
|
||||
case XFER_MW_DMA_1: timings = 0x00012121; break;
|
||||
case XFER_MW_DMA_2: timings = 0x00002020; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
basereg = CS5530_BASEREG(drive->hwif);
|
||||
reg = inl(basereg + 4); /* get drive0 config register */
|
||||
|
|
|
@ -190,7 +190,7 @@ static const struct ide_port_info cs5535_chipset __devinitdata = {
|
|||
.name = "CS5535",
|
||||
.init_hwif = init_hwif_cs5535,
|
||||
.host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
|
||||
IDE_HFLAG_BOOTABLE,
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_BOOTABLE,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = ATA_UDMA4,
|
||||
|
|
|
@ -129,14 +129,18 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif)
|
|||
hwif->set_dma_mode = &hpt34x_set_mode;
|
||||
}
|
||||
|
||||
#define IDE_HFLAGS_HPT34X \
|
||||
(IDE_HFLAG_NO_ATAPI_DMA | \
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE | \
|
||||
IDE_HFLAG_NO_AUTODMA)
|
||||
|
||||
static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
|
||||
{ /* 0 */
|
||||
.name = "HPT343",
|
||||
.init_chipset = init_chipset_hpt34x,
|
||||
.init_hwif = init_hwif_hpt34x,
|
||||
.extra = 16,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
|
||||
IDE_HFLAG_NO_AUTODMA,
|
||||
.host_flags = IDE_HFLAGS_HPT34X,
|
||||
.pio_mask = ATA_PIO5,
|
||||
},
|
||||
{ /* 1 */
|
||||
|
@ -144,9 +148,7 @@ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
|
|||
.init_chipset = init_chipset_hpt34x,
|
||||
.init_hwif = init_hwif_hpt34x,
|
||||
.extra = 16,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
|
||||
IDE_HFLAG_NO_AUTODMA |
|
||||
IDE_HFLAG_OFF_BOARD,
|
||||
.host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD,
|
||||
.pio_mask = ATA_PIO5,
|
||||
#ifdef CONFIG_HPT34X_AUTODMA
|
||||
.swdma_mask = ATA_SWDMA2,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* linux/drivers/ide/pci/hpt366.c Version 1.22 Dec 4, 2007
|
||||
* linux/drivers/ide/pci/hpt366.c Version 1.30 Dec 12, 2007
|
||||
*
|
||||
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
|
||||
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
|
||||
|
@ -88,7 +88,7 @@
|
|||
* - rename all the register related variables consistently
|
||||
* - move all the interrupt twiddling code from the speedproc handlers into
|
||||
* init_hwif_hpt366(), also grouping all the DMA related code together there
|
||||
* - merge two HPT37x speedproc handlers, fix the PIO timing register mask and
|
||||
* - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and
|
||||
* separate the UltraDMA and MWDMA masks there to avoid changing PIO timings
|
||||
* when setting an UltraDMA mode
|
||||
* - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select
|
||||
|
@ -458,6 +458,13 @@ enum ata_clock {
|
|||
NUM_ATA_CLOCKS
|
||||
};
|
||||
|
||||
struct hpt_timings {
|
||||
u32 pio_mask;
|
||||
u32 dma_mask;
|
||||
u32 ultra_mask;
|
||||
u32 *clock_table[NUM_ATA_CLOCKS];
|
||||
};
|
||||
|
||||
/*
|
||||
* Hold all the HighPoint chip information in one place.
|
||||
*/
|
||||
|
@ -468,7 +475,8 @@ struct hpt_info {
|
|||
u8 udma_mask; /* Allowed UltraDMA modes mask. */
|
||||
u8 dpll_clk; /* DPLL clock in MHz */
|
||||
u8 pci_clk; /* PCI clock in MHz */
|
||||
u32 **settings; /* Chipset settings table */
|
||||
struct hpt_timings *timings; /* Chipset timing data */
|
||||
u8 clock; /* ATA clock selected */
|
||||
};
|
||||
|
||||
/* Supported HighPoint chips */
|
||||
|
@ -486,20 +494,30 @@ enum {
|
|||
HPT371N
|
||||
};
|
||||
|
||||
static u32 *hpt36x_settings[NUM_ATA_CLOCKS] = {
|
||||
twenty_five_base_hpt36x,
|
||||
thirty_three_base_hpt36x,
|
||||
forty_base_hpt36x,
|
||||
NULL,
|
||||
NULL
|
||||
static struct hpt_timings hpt36x_timings = {
|
||||
.pio_mask = 0xc1f8ffff,
|
||||
.dma_mask = 0x303800ff,
|
||||
.ultra_mask = 0x30070000,
|
||||
.clock_table = {
|
||||
[ATA_CLOCK_25MHZ] = twenty_five_base_hpt36x,
|
||||
[ATA_CLOCK_33MHZ] = thirty_three_base_hpt36x,
|
||||
[ATA_CLOCK_40MHZ] = forty_base_hpt36x,
|
||||
[ATA_CLOCK_50MHZ] = NULL,
|
||||
[ATA_CLOCK_66MHZ] = NULL
|
||||
}
|
||||
};
|
||||
|
||||
static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = {
|
||||
NULL,
|
||||
thirty_three_base_hpt37x,
|
||||
NULL,
|
||||
fifty_base_hpt37x,
|
||||
sixty_six_base_hpt37x
|
||||
static struct hpt_timings hpt37x_timings = {
|
||||
.pio_mask = 0xcfc3ffff,
|
||||
.dma_mask = 0x31c001ff,
|
||||
.ultra_mask = 0x303c0000,
|
||||
.clock_table = {
|
||||
[ATA_CLOCK_25MHZ] = NULL,
|
||||
[ATA_CLOCK_33MHZ] = thirty_three_base_hpt37x,
|
||||
[ATA_CLOCK_40MHZ] = NULL,
|
||||
[ATA_CLOCK_50MHZ] = fifty_base_hpt37x,
|
||||
[ATA_CLOCK_66MHZ] = sixty_six_base_hpt37x
|
||||
}
|
||||
};
|
||||
|
||||
static const struct hpt_info hpt36x __devinitdata = {
|
||||
|
@ -507,7 +525,7 @@ static const struct hpt_info hpt36x __devinitdata = {
|
|||
.chip_type = HPT36x,
|
||||
.udma_mask = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
|
||||
.dpll_clk = 0, /* no DPLL */
|
||||
.settings = hpt36x_settings
|
||||
.timings = &hpt36x_timings
|
||||
};
|
||||
|
||||
static const struct hpt_info hpt370 __devinitdata = {
|
||||
|
@ -515,7 +533,7 @@ static const struct hpt_info hpt370 __devinitdata = {
|
|||
.chip_type = HPT370,
|
||||
.udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
|
||||
.dpll_clk = 48,
|
||||
.settings = hpt37x_settings
|
||||
.timings = &hpt37x_timings
|
||||
};
|
||||
|
||||
static const struct hpt_info hpt370a __devinitdata = {
|
||||
|
@ -523,7 +541,7 @@ static const struct hpt_info hpt370a __devinitdata = {
|
|||
.chip_type = HPT370A,
|
||||
.udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
|
||||
.dpll_clk = 48,
|
||||
.settings = hpt37x_settings
|
||||
.timings = &hpt37x_timings
|
||||
};
|
||||
|
||||
static const struct hpt_info hpt374 __devinitdata = {
|
||||
|
@ -531,7 +549,7 @@ static const struct hpt_info hpt374 __devinitdata = {
|
|||
.chip_type = HPT374,
|
||||
.udma_mask = ATA_UDMA5,
|
||||
.dpll_clk = 48,
|
||||
.settings = hpt37x_settings
|
||||
.timings = &hpt37x_timings
|
||||
};
|
||||
|
||||
static const struct hpt_info hpt372 __devinitdata = {
|
||||
|
@ -539,7 +557,7 @@ static const struct hpt_info hpt372 __devinitdata = {
|
|||
.chip_type = HPT372,
|
||||
.udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
|
||||
.dpll_clk = 55,
|
||||
.settings = hpt37x_settings
|
||||
.timings = &hpt37x_timings
|
||||
};
|
||||
|
||||
static const struct hpt_info hpt372a __devinitdata = {
|
||||
|
@ -547,7 +565,7 @@ static const struct hpt_info hpt372a __devinitdata = {
|
|||
.chip_type = HPT372A,
|
||||
.udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
|
||||
.dpll_clk = 66,
|
||||
.settings = hpt37x_settings
|
||||
.timings = &hpt37x_timings
|
||||
};
|
||||
|
||||
static const struct hpt_info hpt302 __devinitdata = {
|
||||
|
@ -555,7 +573,7 @@ static const struct hpt_info hpt302 __devinitdata = {
|
|||
.chip_type = HPT302,
|
||||
.udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
|
||||
.dpll_clk = 66,
|
||||
.settings = hpt37x_settings
|
||||
.timings = &hpt37x_timings
|
||||
};
|
||||
|
||||
static const struct hpt_info hpt371 __devinitdata = {
|
||||
|
@ -563,7 +581,7 @@ static const struct hpt_info hpt371 __devinitdata = {
|
|||
.chip_type = HPT371,
|
||||
.udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
|
||||
.dpll_clk = 66,
|
||||
.settings = hpt37x_settings
|
||||
.timings = &hpt37x_timings
|
||||
};
|
||||
|
||||
static const struct hpt_info hpt372n __devinitdata = {
|
||||
|
@ -571,7 +589,7 @@ static const struct hpt_info hpt372n __devinitdata = {
|
|||
.chip_type = HPT372N,
|
||||
.udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
|
||||
.dpll_clk = 77,
|
||||
.settings = hpt37x_settings
|
||||
.timings = &hpt37x_timings
|
||||
};
|
||||
|
||||
static const struct hpt_info hpt302n __devinitdata = {
|
||||
|
@ -579,7 +597,7 @@ static const struct hpt_info hpt302n __devinitdata = {
|
|||
.chip_type = HPT302N,
|
||||
.udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
|
||||
.dpll_clk = 77,
|
||||
.settings = hpt37x_settings
|
||||
.timings = &hpt37x_timings
|
||||
};
|
||||
|
||||
static const struct hpt_info hpt371n __devinitdata = {
|
||||
|
@ -587,7 +605,7 @@ static const struct hpt_info hpt371n __devinitdata = {
|
|||
.chip_type = HPT371N,
|
||||
.udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
|
||||
.dpll_clk = 77,
|
||||
.settings = hpt37x_settings
|
||||
.timings = &hpt37x_timings
|
||||
};
|
||||
|
||||
static int check_in_drive_list(ide_drive_t *drive, const char **list)
|
||||
|
@ -675,69 +693,31 @@ static u32 get_speed_setting(u8 speed, struct hpt_info *info)
|
|||
for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
|
||||
if (xfer_speeds[i] == speed)
|
||||
break;
|
||||
/*
|
||||
* NOTE: info->settings only points to the pointer
|
||||
* to the list of the actual register values
|
||||
*/
|
||||
return (*info->settings)[i];
|
||||
}
|
||||
|
||||
static void hpt36x_set_mode(ide_drive_t *drive, const u8 speed)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct pci_dev *dev = hwif->pci_dev;
|
||||
struct hpt_info *info = pci_get_drvdata(dev);
|
||||
u8 itr_addr = drive->dn ? 0x44 : 0x40;
|
||||
u32 old_itr = 0;
|
||||
u32 itr_mask, new_itr;
|
||||
|
||||
itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 :
|
||||
(speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff);
|
||||
|
||||
new_itr = get_speed_setting(speed, info);
|
||||
|
||||
/*
|
||||
* Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)
|
||||
* to avoid problems handling I/O errors later
|
||||
*/
|
||||
pci_read_config_dword(dev, itr_addr, &old_itr);
|
||||
new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);
|
||||
new_itr &= ~0xc0000000;
|
||||
|
||||
pci_write_config_dword(dev, itr_addr, new_itr);
|
||||
}
|
||||
|
||||
static void hpt37x_set_mode(ide_drive_t *drive, const u8 speed)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct pci_dev *dev = hwif->pci_dev;
|
||||
struct hpt_info *info = pci_get_drvdata(dev);
|
||||
u8 itr_addr = 0x40 + (drive->dn * 4);
|
||||
u32 old_itr = 0;
|
||||
u32 itr_mask, new_itr;
|
||||
|
||||
itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 :
|
||||
(speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff);
|
||||
|
||||
new_itr = get_speed_setting(speed, info);
|
||||
|
||||
pci_read_config_dword(dev, itr_addr, &old_itr);
|
||||
new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);
|
||||
|
||||
if (speed < XFER_MW_DMA_0)
|
||||
new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
|
||||
pci_write_config_dword(dev, itr_addr, new_itr);
|
||||
return info->timings->clock_table[info->clock][i];
|
||||
}
|
||||
|
||||
static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct hpt_info *info = pci_get_drvdata(hwif->pci_dev);
|
||||
struct pci_dev *dev = HWIF(drive)->pci_dev;
|
||||
struct hpt_info *info = pci_get_drvdata(dev);
|
||||
struct hpt_timings *t = info->timings;
|
||||
u8 itr_addr = 0x40 + (drive->dn * 4);
|
||||
u32 old_itr = 0;
|
||||
u32 new_itr = get_speed_setting(speed, info);
|
||||
u32 itr_mask = speed < XFER_MW_DMA_0 ? t->pio_mask :
|
||||
(speed < XFER_UDMA_0 ? t->dma_mask :
|
||||
t->ultra_mask);
|
||||
|
||||
if (info->chip_type >= HPT370)
|
||||
hpt37x_set_mode(drive, speed);
|
||||
else /* hpt368: hpt_minimum_revision(dev, 2) */
|
||||
hpt36x_set_mode(drive, speed);
|
||||
pci_read_config_dword(dev, itr_addr, &old_itr);
|
||||
new_itr = (old_itr & ~itr_mask) | (new_itr & itr_mask);
|
||||
/*
|
||||
* Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)
|
||||
* to avoid problems handling I/O errors later
|
||||
*/
|
||||
new_itr &= ~0xc0000000;
|
||||
|
||||
pci_write_config_dword(dev, itr_addr, new_itr);
|
||||
}
|
||||
|
||||
static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
|
@ -756,15 +736,6 @@ static int hpt3xx_quirkproc(ide_drive_t *drive)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void hpt3xx_intrproc(ide_drive_t *drive)
|
||||
{
|
||||
if (drive->quirk_list)
|
||||
return;
|
||||
|
||||
/* drives in the quirk_list may not like intr setups/cleanups */
|
||||
outb(drive->ctl | 2, IDE_CONTROL_REG);
|
||||
}
|
||||
|
||||
static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
|
@ -914,32 +885,33 @@ static int hpt374_ide_dma_end(ide_drive_t *drive)
|
|||
|
||||
static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
|
||||
{
|
||||
u8 scr2 = inb(hwif->dma_master + 0x7b);
|
||||
unsigned long base = hwif->extra_base;
|
||||
u8 scr2 = inb(base + 0x6b);
|
||||
|
||||
if ((scr2 & 0x7f) == mode)
|
||||
return;
|
||||
|
||||
/* Tristate the bus */
|
||||
outb(0x80, hwif->dma_master + 0x73);
|
||||
outb(0x80, hwif->dma_master + 0x77);
|
||||
outb(0x80, base + 0x63);
|
||||
outb(0x80, base + 0x67);
|
||||
|
||||
/* Switch clock and reset channels */
|
||||
outb(mode, hwif->dma_master + 0x7b);
|
||||
outb(0xc0, hwif->dma_master + 0x79);
|
||||
outb(mode, base + 0x6b);
|
||||
outb(0xc0, base + 0x69);
|
||||
|
||||
/*
|
||||
* Reset the state machines.
|
||||
* NOTE: avoid accidentally enabling the disabled channels.
|
||||
*/
|
||||
outb(inb(hwif->dma_master + 0x70) | 0x32, hwif->dma_master + 0x70);
|
||||
outb(inb(hwif->dma_master + 0x74) | 0x32, hwif->dma_master + 0x74);
|
||||
outb(inb(base + 0x60) | 0x32, base + 0x60);
|
||||
outb(inb(base + 0x64) | 0x32, base + 0x64);
|
||||
|
||||
/* Complete reset */
|
||||
outb(0x00, hwif->dma_master + 0x79);
|
||||
outb(0x00, base + 0x69);
|
||||
|
||||
/* Reconnect channels to bus */
|
||||
outb(0x00, hwif->dma_master + 0x73);
|
||||
outb(0x00, hwif->dma_master + 0x77);
|
||||
outb(0x00, base + 0x63);
|
||||
outb(0x00, base + 0x67);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1210,7 +1182,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
|
|||
* We also don't like using the DPLL because this causes glitches
|
||||
* on PRST-/SRST- when the state engine gets reset...
|
||||
*/
|
||||
if (chip_type >= HPT374 || info->settings[clock] == NULL) {
|
||||
if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) {
|
||||
u16 f_low, delta = pci_clk < 50 ? 2 : 4;
|
||||
int adjust;
|
||||
|
||||
|
@ -1226,7 +1198,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
|
|||
clock = ATA_CLOCK_50MHZ;
|
||||
}
|
||||
|
||||
if (info->settings[clock] == NULL) {
|
||||
if (info->timings->clock_table[clock] == NULL) {
|
||||
printk(KERN_ERR "%s: unknown bus timing!\n", name);
|
||||
kfree(info);
|
||||
return -EIO;
|
||||
|
@ -1267,15 +1239,10 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
|
|||
printk("%s: using %d MHz PCI clock\n", name, pci_clk);
|
||||
}
|
||||
|
||||
/*
|
||||
* Advance the table pointer to a slot which points to the list
|
||||
* of the register values settings matching the clock being used.
|
||||
*/
|
||||
info->settings += clock;
|
||||
|
||||
/* Store the clock frequencies. */
|
||||
info->dpll_clk = dpll_clk;
|
||||
info->pci_clk = pci_clk;
|
||||
info->clock = clock;
|
||||
|
||||
/* Point to this chip's own instance of the hpt_info structure. */
|
||||
pci_set_drvdata(dev, info);
|
||||
|
@ -1320,8 +1287,8 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
|
|||
|
||||
hwif->set_pio_mode = &hpt3xx_set_pio_mode;
|
||||
hwif->set_dma_mode = &hpt3xx_set_mode;
|
||||
|
||||
hwif->quirkproc = &hpt3xx_quirkproc;
|
||||
hwif->intrproc = &hpt3xx_intrproc;
|
||||
hwif->maskproc = &hpt3xx_maskproc;
|
||||
hwif->busproc = &hpt3xx_busproc;
|
||||
|
||||
|
@ -1494,6 +1461,11 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define IDE_HFLAGS_HPT3XX \
|
||||
(IDE_HFLAG_NO_ATAPI_DMA | \
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE | \
|
||||
IDE_HFLAG_OFF_BOARD)
|
||||
|
||||
static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
|
||||
{ /* 0 */
|
||||
.name = "HPT36x",
|
||||
|
@ -1508,9 +1480,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
|
|||
*/
|
||||
.enablebits = {{0x50,0x10,0x10}, {0x54,0x04,0x04}},
|
||||
.extra = 240,
|
||||
.host_flags = IDE_HFLAG_SINGLE |
|
||||
IDE_HFLAG_NO_ATAPI_DMA |
|
||||
IDE_HFLAG_OFF_BOARD,
|
||||
.host_flags = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
},{ /* 1 */
|
||||
|
@ -1520,7 +1490,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
|
|||
.init_dma = init_dma_hpt366,
|
||||
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
|
||||
.extra = 240,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
|
||||
.host_flags = IDE_HFLAGS_HPT3XX,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
},{ /* 2 */
|
||||
|
@ -1530,7 +1500,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
|
|||
.init_dma = init_dma_hpt366,
|
||||
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
|
||||
.extra = 240,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
|
||||
.host_flags = IDE_HFLAGS_HPT3XX,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
},{ /* 3 */
|
||||
|
@ -1540,7 +1510,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
|
|||
.init_dma = init_dma_hpt366,
|
||||
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
|
||||
.extra = 240,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
|
||||
.host_flags = IDE_HFLAGS_HPT3XX,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
},{ /* 4 */
|
||||
|
@ -1551,7 +1521,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
|
|||
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
|
||||
.udma_mask = ATA_UDMA5,
|
||||
.extra = 240,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
|
||||
.host_flags = IDE_HFLAGS_HPT3XX,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
},{ /* 5 */
|
||||
|
@ -1561,7 +1531,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
|
|||
.init_dma = init_dma_hpt366,
|
||||
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
|
||||
.extra = 240,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
|
||||
.host_flags = IDE_HFLAGS_HPT3XX,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
}
|
||||
|
|
|
@ -101,24 +101,11 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
pci_read_config_byte(dev, 0x54, ®54);
|
||||
pci_read_config_byte(dev, 0x55, ®55);
|
||||
|
||||
switch(speed) {
|
||||
case XFER_UDMA_6:
|
||||
case XFER_UDMA_4:
|
||||
case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
|
||||
case XFER_UDMA_5:
|
||||
case XFER_UDMA_3:
|
||||
case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
|
||||
case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
|
||||
break;
|
||||
case XFER_MW_DMA_2:
|
||||
case XFER_MW_DMA_1:
|
||||
case XFER_SW_DMA_2:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (speed >= XFER_UDMA_0) {
|
||||
u8 udma = speed - XFER_UDMA_0;
|
||||
|
||||
u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
|
||||
|
||||
if (!(reg48 & u_flag))
|
||||
pci_write_config_byte(dev, 0x48, reg48 | u_flag);
|
||||
if (speed >= XFER_UDMA_5) {
|
||||
|
|
|
@ -146,7 +146,7 @@ static struct udma_timing {
|
|||
{ 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */
|
||||
};
|
||||
|
||||
static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
|
||||
static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
|
||||
|
@ -162,45 +162,18 @@ static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
|
|||
if (max_dma_rate(hwif->pci_dev) == 4) {
|
||||
u8 mode = speed & 0x07;
|
||||
|
||||
switch (speed) {
|
||||
case XFER_UDMA_6:
|
||||
case XFER_UDMA_5:
|
||||
case XFER_UDMA_4:
|
||||
case XFER_UDMA_3:
|
||||
case XFER_UDMA_2:
|
||||
case XFER_UDMA_1:
|
||||
case XFER_UDMA_0:
|
||||
if (speed >= XFER_UDMA_0) {
|
||||
set_indexed_reg(hwif, 0x10 + adj,
|
||||
udma_timings[mode].reg10);
|
||||
set_indexed_reg(hwif, 0x11 + adj,
|
||||
udma_timings[mode].reg11);
|
||||
set_indexed_reg(hwif, 0x12 + adj,
|
||||
udma_timings[mode].reg12);
|
||||
break;
|
||||
|
||||
case XFER_MW_DMA_2:
|
||||
case XFER_MW_DMA_1:
|
||||
case XFER_MW_DMA_0:
|
||||
} else {
|
||||
set_indexed_reg(hwif, 0x0e + adj,
|
||||
mwdma_timings[mode].reg0e);
|
||||
set_indexed_reg(hwif, 0x0f + adj,
|
||||
mwdma_timings[mode].reg0f);
|
||||
break;
|
||||
case XFER_PIO_4:
|
||||
case XFER_PIO_3:
|
||||
case XFER_PIO_2:
|
||||
case XFER_PIO_1:
|
||||
case XFER_PIO_0:
|
||||
set_indexed_reg(hwif, 0x0c + adj,
|
||||
pio_timings[mode].reg0c);
|
||||
set_indexed_reg(hwif, 0x0d + adj,
|
||||
pio_timings[mode].reg0d);
|
||||
set_indexed_reg(hwif, 0x13 + adj,
|
||||
pio_timings[mode].reg13);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "pdc202xx_new: "
|
||||
"Unknown speed %d ignored\n", speed);
|
||||
}
|
||||
} else if (speed == XFER_UDMA_2) {
|
||||
/* Set tHOLD bit to 0 if using UDMA mode 2 */
|
||||
|
@ -212,7 +185,14 @@ static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
|
|||
|
||||
static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
{
|
||||
pdcnew_set_mode(drive, XFER_PIO_0 + pio);
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
|
||||
|
||||
if (max_dma_rate(hwif->pci_dev) == 4) {
|
||||
set_indexed_reg(hwif, 0x0c + adj, pio_timings[pio].reg0c);
|
||||
set_indexed_reg(hwif, 0x0d + adj, pio_timings[pio].reg0d);
|
||||
set_indexed_reg(hwif, 0x13 + adj, pio_timings[pio].reg13);
|
||||
}
|
||||
}
|
||||
|
||||
static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
|
||||
|
@ -466,7 +446,7 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
|
|||
static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
|
||||
{
|
||||
hwif->set_pio_mode = &pdcnew_set_pio_mode;
|
||||
hwif->set_dma_mode = &pdcnew_set_mode;
|
||||
hwif->set_dma_mode = &pdcnew_set_dma_mode;
|
||||
|
||||
hwif->quirkproc = &pdcnew_quirkproc;
|
||||
hwif->resetproc = &pdcnew_reset;
|
||||
|
|
|
@ -162,7 +162,7 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
|
|||
*/
|
||||
static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
|
||||
{
|
||||
unsigned long clock_reg = hwif->dma_master + 0x11;
|
||||
unsigned long clock_reg = hwif->extra_base + 0x01;
|
||||
u8 clock = inb(clock_reg);
|
||||
|
||||
outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
|
||||
|
@ -170,7 +170,7 @@ static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
|
|||
|
||||
static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
|
||||
{
|
||||
unsigned long clock_reg = hwif->dma_master + 0x11;
|
||||
unsigned long clock_reg = hwif->extra_base + 0x01;
|
||||
u8 clock = inb(clock_reg);
|
||||
|
||||
outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
|
||||
|
@ -193,7 +193,7 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
|
|||
if (drive->media != ide_disk || drive->addressing == 1) {
|
||||
struct request *rq = HWGROUP(drive)->rq;
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
unsigned long high_16 = hwif->dma_master;
|
||||
unsigned long high_16 = hwif->extra_base - 16;
|
||||
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
|
||||
u32 word_count = 0;
|
||||
u8 clock = inb(high_16 + 0x11);
|
||||
|
@ -212,7 +212,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
|
|||
{
|
||||
if (drive->media != ide_disk || drive->addressing == 1) {
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
unsigned long high_16 = hwif->dma_master;
|
||||
unsigned long high_16 = hwif->extra_base - 16;
|
||||
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
|
||||
u8 clock = 0;
|
||||
|
||||
|
@ -228,7 +228,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
|
|||
static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
unsigned long high_16 = hwif->dma_master;
|
||||
unsigned long high_16 = hwif->extra_base - 16;
|
||||
u8 dma_stat = inb(hwif->dma_status);
|
||||
u8 sc1d = inb(high_16 + 0x001d);
|
||||
|
||||
|
@ -271,7 +271,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive)
|
|||
|
||||
static void pdc202xx_reset_host (ide_hwif_t *hwif)
|
||||
{
|
||||
unsigned long high_16 = hwif->dma_master;
|
||||
unsigned long high_16 = hwif->extra_base - 16;
|
||||
u8 udma_speed_flag = inb(high_16 | 0x001f);
|
||||
|
||||
outb(udma_speed_flag | 0x10, high_16 | 0x001f);
|
||||
|
@ -375,6 +375,11 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
|
|||
}
|
||||
}
|
||||
|
||||
#define IDE_HFLAGS_PDC202XX \
|
||||
(IDE_HFLAG_ERROR_STOPS_FIFO | \
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE | \
|
||||
IDE_HFLAG_OFF_BOARD)
|
||||
|
||||
#define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \
|
||||
{ \
|
||||
.name = name_str, \
|
||||
|
@ -382,9 +387,7 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
|
|||
.init_hwif = init_hwif_pdc202xx, \
|
||||
.init_dma = init_dma_pdc202xx, \
|
||||
.extra = 48, \
|
||||
.host_flags = IDE_HFLAG_ERROR_STOPS_FIFO | \
|
||||
extra_flags | \
|
||||
IDE_HFLAG_OFF_BOARD, \
|
||||
.host_flags = IDE_HFLAGS_PDC202XX | extra_flags, \
|
||||
.pio_mask = ATA_PIO4, \
|
||||
.mwdma_mask = ATA_MWDMA2, \
|
||||
.udma_mask = udma, \
|
||||
|
@ -397,8 +400,7 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
|
|||
.init_hwif = init_hwif_pdc202xx,
|
||||
.init_dma = init_dma_pdc202xx,
|
||||
.extra = 16,
|
||||
.host_flags = IDE_HFLAG_ERROR_STOPS_FIFO |
|
||||
IDE_HFLAG_OFF_BOARD,
|
||||
.host_flags = IDE_HFLAGS_PDC202XX,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = ATA_UDMA2,
|
||||
|
|
|
@ -203,20 +203,11 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
pci_read_config_byte(dev, 0x54, ®54);
|
||||
pci_read_config_byte(dev, 0x55, ®55);
|
||||
|
||||
switch(speed) {
|
||||
case XFER_UDMA_4:
|
||||
case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
|
||||
case XFER_UDMA_5:
|
||||
case XFER_UDMA_3:
|
||||
case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
|
||||
case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
|
||||
case XFER_MW_DMA_2:
|
||||
case XFER_MW_DMA_1:
|
||||
case XFER_SW_DMA_2: break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
if (speed >= XFER_UDMA_0) {
|
||||
u8 udma = speed - XFER_UDMA_0;
|
||||
|
||||
u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
|
||||
|
||||
if (!(reg48 & u_flag))
|
||||
pci_write_config_byte(dev, 0x48, reg48 | u_flag);
|
||||
if (speed == XFER_UDMA_5) {
|
||||
|
|
|
@ -135,59 +135,29 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
|||
unsigned short pci_clock;
|
||||
unsigned int basereg = hwif->channel ? 0x50 : 0x40;
|
||||
|
||||
static const u32 udma_timing[3][3] = {
|
||||
{ 0x00921250, 0x00911140, 0x00911030 },
|
||||
{ 0x00932470, 0x00922260, 0x00922140 },
|
||||
{ 0x009436a1, 0x00933481, 0x00923261 },
|
||||
};
|
||||
|
||||
static const u32 mwdma_timing[3][3] = {
|
||||
{ 0x00077771, 0x00012121, 0x00002020 },
|
||||
{ 0x000bbbb2, 0x00024241, 0x00013131 },
|
||||
{ 0x000ffff3, 0x00035352, 0x00015151 },
|
||||
};
|
||||
|
||||
pci_clock = sc1200_get_pci_clock();
|
||||
|
||||
/*
|
||||
* Note that each DMA mode has several timings associated with it.
|
||||
* The correct timing depends on the fast PCI clock freq.
|
||||
*/
|
||||
timings = 0;
|
||||
switch (mode) {
|
||||
case XFER_UDMA_0:
|
||||
switch (pci_clock) {
|
||||
case PCI_CLK_33: timings = 0x00921250; break;
|
||||
case PCI_CLK_48: timings = 0x00932470; break;
|
||||
case PCI_CLK_66: timings = 0x009436a1; break;
|
||||
}
|
||||
break;
|
||||
case XFER_UDMA_1:
|
||||
switch (pci_clock) {
|
||||
case PCI_CLK_33: timings = 0x00911140; break;
|
||||
case PCI_CLK_48: timings = 0x00922260; break;
|
||||
case PCI_CLK_66: timings = 0x00933481; break;
|
||||
}
|
||||
break;
|
||||
case XFER_UDMA_2:
|
||||
switch (pci_clock) {
|
||||
case PCI_CLK_33: timings = 0x00911030; break;
|
||||
case PCI_CLK_48: timings = 0x00922140; break;
|
||||
case PCI_CLK_66: timings = 0x00923261; break;
|
||||
}
|
||||
break;
|
||||
case XFER_MW_DMA_0:
|
||||
switch (pci_clock) {
|
||||
case PCI_CLK_33: timings = 0x00077771; break;
|
||||
case PCI_CLK_48: timings = 0x000bbbb2; break;
|
||||
case PCI_CLK_66: timings = 0x000ffff3; break;
|
||||
}
|
||||
break;
|
||||
case XFER_MW_DMA_1:
|
||||
switch (pci_clock) {
|
||||
case PCI_CLK_33: timings = 0x00012121; break;
|
||||
case PCI_CLK_48: timings = 0x00024241; break;
|
||||
case PCI_CLK_66: timings = 0x00035352; break;
|
||||
}
|
||||
break;
|
||||
case XFER_MW_DMA_2:
|
||||
switch (pci_clock) {
|
||||
case PCI_CLK_33: timings = 0x00002020; break;
|
||||
case PCI_CLK_48: timings = 0x00013131; break;
|
||||
case PCI_CLK_66: timings = 0x00015151; break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode >= XFER_UDMA_0)
|
||||
timings = udma_timing[pci_clock][mode - XFER_UDMA_0];
|
||||
else
|
||||
timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0];
|
||||
|
||||
if (unit == 0) { /* are we configuring drive0? */
|
||||
pci_read_config_dword(hwif->pci_dev, basereg+4, ®);
|
||||
|
@ -260,66 +230,39 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev)
|
||||
{
|
||||
int h;
|
||||
|
||||
for (h = 0; h < MAX_HWIFS; h++) {
|
||||
ide_hwif_t *hwif = &ide_hwifs[h];
|
||||
if (prev) {
|
||||
if (hwif == prev)
|
||||
prev = NULL; // found previous, now look for next match
|
||||
} else {
|
||||
if (hwif && hwif->pci_dev == dev)
|
||||
return hwif; // found next match
|
||||
}
|
||||
}
|
||||
return NULL; // not found
|
||||
}
|
||||
|
||||
typedef struct sc1200_saved_state_s {
|
||||
__u32 regs[4];
|
||||
} sc1200_saved_state_t;
|
||||
|
||||
struct sc1200_saved_state {
|
||||
u32 regs[8];
|
||||
};
|
||||
|
||||
static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
|
||||
{
|
||||
ide_hwif_t *hwif = NULL;
|
||||
|
||||
printk("SC1200: suspend(%u)\n", state.event);
|
||||
|
||||
/*
|
||||
* we only save state when going from full power to less
|
||||
*/
|
||||
if (state.event == PM_EVENT_ON) {
|
||||
// we only save state when going from full power to less
|
||||
struct sc1200_saved_state *ss;
|
||||
unsigned int r;
|
||||
|
||||
//
|
||||
// Loop over all interfaces that are part of this PCI device:
|
||||
//
|
||||
while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
|
||||
sc1200_saved_state_t *ss;
|
||||
unsigned int basereg, r;
|
||||
//
|
||||
// allocate a permanent save area, if not already allocated
|
||||
//
|
||||
ss = (sc1200_saved_state_t *)hwif->config_data;
|
||||
/*
|
||||
* allocate a permanent save area, if not already allocated
|
||||
*/
|
||||
ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
|
||||
if (ss == NULL) {
|
||||
ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL);
|
||||
ss = kmalloc(sizeof(*ss), GFP_KERNEL);
|
||||
if (ss == NULL)
|
||||
return -ENOMEM;
|
||||
hwif->config_data = (unsigned long)ss;
|
||||
}
|
||||
ss = (sc1200_saved_state_t *)hwif->config_data;
|
||||
//
|
||||
// Save timing registers: this may be unnecessary if
|
||||
// BIOS also does it
|
||||
//
|
||||
basereg = hwif->channel ? 0x50 : 0x40;
|
||||
for (r = 0; r < 4; ++r) {
|
||||
pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]);
|
||||
}
|
||||
}
|
||||
pci_set_drvdata(dev, ss);
|
||||
}
|
||||
|
||||
/* You don't need to iterate over disks -- sysfs should have done that for you already */
|
||||
/*
|
||||
* save timing registers
|
||||
* (this may be unnecessary if BIOS also does it)
|
||||
*/
|
||||
for (r = 0; r < 8; r++)
|
||||
pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]);
|
||||
}
|
||||
|
||||
pci_disable_device(dev);
|
||||
pci_set_power_state(dev, pci_choose_state(dev, state));
|
||||
|
@ -328,30 +271,25 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
|
|||
|
||||
static int sc1200_resume (struct pci_dev *dev)
|
||||
{
|
||||
ide_hwif_t *hwif = NULL;
|
||||
struct sc1200_saved_state *ss;
|
||||
unsigned int r;
|
||||
int i;
|
||||
|
||||
i = pci_enable_device(dev);
|
||||
if (i)
|
||||
return i;
|
||||
|
||||
//
|
||||
// loop over all interfaces that are part of this pci device:
|
||||
//
|
||||
while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
|
||||
unsigned int basereg, r;
|
||||
sc1200_saved_state_t *ss = (sc1200_saved_state_t *)hwif->config_data;
|
||||
ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
|
||||
|
||||
//
|
||||
// Restore timing registers: this may be unnecessary if BIOS also does it
|
||||
//
|
||||
basereg = hwif->channel ? 0x50 : 0x40;
|
||||
if (ss != NULL) {
|
||||
for (r = 0; r < 4; ++r) {
|
||||
pci_write_config_dword(hwif->pci_dev, basereg + (r<<2), ss->regs[r]);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* restore timing registers
|
||||
* (this may be unnecessary if BIOS also does it)
|
||||
*/
|
||||
if (ss) {
|
||||
for (r = 0; r < 8; r++)
|
||||
pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -254,19 +254,7 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
offset = 0; /* 100MHz */
|
||||
}
|
||||
|
||||
switch (speed) {
|
||||
case XFER_UDMA_6:
|
||||
case XFER_UDMA_5:
|
||||
case XFER_UDMA_4:
|
||||
case XFER_UDMA_3:
|
||||
case XFER_UDMA_2:
|
||||
case XFER_UDMA_1:
|
||||
case XFER_UDMA_0:
|
||||
idx = speed - XFER_UDMA_0;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
jcactsel = JCACTSELtbl[offset][idx];
|
||||
if (is_slave) {
|
||||
|
|
|
@ -366,12 +366,17 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
|
|||
}
|
||||
}
|
||||
|
||||
#define IDE_HFLAGS_SVWKS \
|
||||
(IDE_HFLAG_LEGACY_IRQS | \
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE | \
|
||||
IDE_HFLAG_BOOTABLE)
|
||||
|
||||
static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
|
||||
{ /* 0 */
|
||||
.name = "SvrWks OSB4",
|
||||
.init_chipset = init_chipset_svwks,
|
||||
.init_hwif = init_hwif_svwks,
|
||||
.host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
|
||||
.host_flags = IDE_HFLAGS_SVWKS,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = 0x00, /* UDMA is problematic on OSB4 */
|
||||
|
@ -379,7 +384,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
|
|||
.name = "SvrWks CSB5",
|
||||
.init_chipset = init_chipset_svwks,
|
||||
.init_hwif = init_hwif_svwks,
|
||||
.host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
|
||||
.host_flags = IDE_HFLAGS_SVWKS,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = ATA_UDMA5,
|
||||
|
@ -387,7 +392,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
|
|||
.name = "SvrWks CSB6",
|
||||
.init_chipset = init_chipset_svwks,
|
||||
.init_hwif = init_hwif_svwks,
|
||||
.host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
|
||||
.host_flags = IDE_HFLAGS_SVWKS,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = ATA_UDMA5,
|
||||
|
@ -395,8 +400,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
|
|||
.name = "SvrWks CSB6",
|
||||
.init_chipset = init_chipset_svwks,
|
||||
.init_hwif = init_hwif_svwks,
|
||||
.host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE |
|
||||
IDE_HFLAG_BOOTABLE,
|
||||
.host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = ATA_UDMA5,
|
||||
|
@ -404,8 +408,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
|
|||
.name = "SvrWks HT1000",
|
||||
.init_chipset = init_chipset_svwks,
|
||||
.init_hwif = init_hwif_svwks,
|
||||
.host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE |
|
||||
IDE_HFLAG_BOOTABLE,
|
||||
.host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = ATA_UDMA5,
|
||||
|
|
|
@ -582,7 +582,6 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
|
|||
hwif->pre_reset = NULL; /* No HBA specific pre_set needed */
|
||||
hwif->resetproc = &sgiioc4_resetproc;/* Reset DMA engine,
|
||||
clear interrupts */
|
||||
hwif->intrproc = NULL; /* Enable or Disable interrupt from drive */
|
||||
hwif->maskproc = &sgiioc4_maskproc; /* Mask on/off NIEN register */
|
||||
hwif->quirkproc = NULL;
|
||||
hwif->busproc = NULL;
|
||||
|
|
|
@ -278,27 +278,14 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
|
||||
scsc = is_sata(hwif) ? 1 : scsc;
|
||||
|
||||
switch(speed) {
|
||||
case XFER_MW_DMA_2:
|
||||
case XFER_MW_DMA_1:
|
||||
case XFER_MW_DMA_0:
|
||||
multi = dma[speed - XFER_MW_DMA_0];
|
||||
mode |= ((unit) ? 0x20 : 0x02);
|
||||
break;
|
||||
case XFER_UDMA_6:
|
||||
case XFER_UDMA_5:
|
||||
case XFER_UDMA_4:
|
||||
case XFER_UDMA_3:
|
||||
case XFER_UDMA_2:
|
||||
case XFER_UDMA_1:
|
||||
case XFER_UDMA_0:
|
||||
if (speed >= XFER_UDMA_0) {
|
||||
multi = dma[2];
|
||||
ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) :
|
||||
(ultra5[speed - XFER_UDMA_0]));
|
||||
mode |= ((unit) ? 0x30 : 0x03);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
ultra |= (scsc ? ultra6[speed - XFER_UDMA_0] :
|
||||
ultra5[speed - XFER_UDMA_0]);
|
||||
mode |= (unit ? 0x30 : 0x03);
|
||||
} else {
|
||||
multi = dma[speed - XFER_MW_DMA_0];
|
||||
mode |= (unit ? 0x20 : 0x02);
|
||||
}
|
||||
|
||||
if (hwif->mmio) {
|
||||
|
|
|
@ -305,59 +305,56 @@ static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
|||
sis_program_timings(drive, XFER_PIO_0 + pio);
|
||||
}
|
||||
|
||||
static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct pci_dev *dev = hwif->pci_dev;
|
||||
|
||||
/* Config chip for mode */
|
||||
switch(speed) {
|
||||
case XFER_UDMA_6:
|
||||
case XFER_UDMA_5:
|
||||
case XFER_UDMA_4:
|
||||
case XFER_UDMA_3:
|
||||
case XFER_UDMA_2:
|
||||
case XFER_UDMA_1:
|
||||
case XFER_UDMA_0:
|
||||
if (chipset_family >= ATA_133) {
|
||||
struct pci_dev *dev = drive->hwif->pci_dev;
|
||||
u32 regdw = 0;
|
||||
u8 drive_pci = sis_ata133_get_base(drive);
|
||||
u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
|
||||
|
||||
pci_read_config_dword(dev, drive_pci, ®dw);
|
||||
|
||||
regdw |= 0x04;
|
||||
regdw &= 0xfffff00f;
|
||||
/* check if ATA133 enable */
|
||||
if (regdw & 0x08) {
|
||||
regdw |= (unsigned long)cycle_time_value[ATA_133][speed-XFER_UDMA_0] << 4;
|
||||
regdw |= (unsigned long)cvs_time_value[ATA_133][speed-XFER_UDMA_0] << 8;
|
||||
} else {
|
||||
regdw |= (unsigned long)cycle_time_value[ATA_100][speed-XFER_UDMA_0] << 4;
|
||||
regdw |= (unsigned long)cvs_time_value[ATA_100][speed-XFER_UDMA_0] << 8;
|
||||
}
|
||||
pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
|
||||
} else {
|
||||
u8 drive_pci = 0x40 + drive->dn * 2, reg = 0;
|
||||
clk = (regdw & 0x08) ? ATA_133 : ATA_100;
|
||||
idx = mode - XFER_UDMA_0;
|
||||
regdw |= cycle_time_value[clk][idx] << 4;
|
||||
regdw |= cvs_time_value[clk][idx] << 8;
|
||||
|
||||
pci_read_config_byte(dev, drive_pci+1, ®);
|
||||
/* Force the UDMA bit on if we want to use UDMA */
|
||||
pci_write_config_dword(dev, drive_pci, regdw);
|
||||
}
|
||||
|
||||
static void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode)
|
||||
{
|
||||
struct pci_dev *dev = drive->hwif->pci_dev;
|
||||
u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family;
|
||||
|
||||
pci_read_config_byte(dev, drive_pci + 1, ®);
|
||||
|
||||
/* force the UDMA bit on if we want to use UDMA */
|
||||
reg |= 0x80;
|
||||
/* clean reg cycle time bits */
|
||||
reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family]))
|
||||
<< cycle_time_offset[chipset_family]);
|
||||
reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]);
|
||||
/* set reg cycle time bits */
|
||||
reg |= cycle_time_value[chipset_family][speed-XFER_UDMA_0]
|
||||
<< cycle_time_offset[chipset_family];
|
||||
pci_write_config_byte(dev, drive_pci+1, reg);
|
||||
}
|
||||
break;
|
||||
case XFER_MW_DMA_2:
|
||||
case XFER_MW_DMA_1:
|
||||
case XFER_MW_DMA_0:
|
||||
reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i];
|
||||
|
||||
pci_write_config_byte(dev, drive_pci + 1, reg);
|
||||
}
|
||||
|
||||
static void sis_program_udma_timings(ide_drive_t *drive, const u8 mode)
|
||||
{
|
||||
if (chipset_family >= ATA_133) /* ATA_133 */
|
||||
sis_ata133_program_udma_timings(drive, mode);
|
||||
else /* ATA_33/66/100a/100/133a */
|
||||
sis_ata33_program_udma_timings(drive, mode);
|
||||
}
|
||||
|
||||
static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
{
|
||||
if (speed >= XFER_UDMA_0)
|
||||
sis_program_udma_timings(drive, speed);
|
||||
else
|
||||
sis_program_timings(drive, speed);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
|
||||
|
|
|
@ -115,10 +115,6 @@ static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n",
|
||||
drive->name, ide_xfer_verbose(speed)));
|
||||
|
||||
switch (speed) {
|
||||
case XFER_MW_DMA_2:
|
||||
case XFER_MW_DMA_1:
|
||||
case XFER_MW_DMA_0:
|
||||
drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
|
||||
|
||||
/*
|
||||
|
@ -138,10 +134,6 @@ static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
|
||||
pci_write_config_word(dev, reg, drv_ctrl);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -91,19 +91,9 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
pci_read_config_word(dev, 0x48, ®48);
|
||||
pci_read_config_word(dev, 0x4a, ®4a);
|
||||
|
||||
switch(speed) {
|
||||
case XFER_UDMA_4: u_speed = 4 << (drive->dn * 4); break;
|
||||
case XFER_UDMA_3: u_speed = 3 << (drive->dn * 4); break;
|
||||
case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
|
||||
case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
|
||||
case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
|
||||
case XFER_MW_DMA_2:
|
||||
case XFER_MW_DMA_1:
|
||||
case XFER_SW_DMA_2: break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
if (speed >= XFER_UDMA_0) {
|
||||
u_speed = (speed - XFER_UDMA_0) << (drive->dn * 4);
|
||||
|
||||
if (!(reg48 & u_flag))
|
||||
pci_write_config_word(dev, 0x48, reg48|u_flag);
|
||||
/* FIXME: (reg4a & a_speed) ? */
|
||||
|
|
|
@ -222,7 +222,8 @@ static const struct ide_port_info tc86c001_chipset __devinitdata = {
|
|||
.name = "TC86C001",
|
||||
.init_chipset = init_chipset_tc86c001,
|
||||
.init_hwif = init_hwif_tc86c001,
|
||||
.host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
|
||||
.host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD |
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = ATA_UDMA4,
|
||||
|
|
|
@ -81,8 +81,6 @@ static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
|
|||
case XFER_PIO_0:
|
||||
timing = 0x0808;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
triflex_timings &= ~(0xFFFF << (16 * unit));
|
||||
|
|
|
@ -439,6 +439,7 @@ static const struct ide_port_info via82cxxx_chipset __devinitdata = {
|
|||
.enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
|
||||
.host_flags = IDE_HFLAG_PIO_NO_BLACKLIST |
|
||||
IDE_HFLAG_PIO_NO_DOWNGRADE |
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE |
|
||||
IDE_HFLAG_POST_SET_MODE |
|
||||
IDE_HFLAG_IO_32BIT |
|
||||
IDE_HFLAG_BOOTABLE,
|
||||
|
|
|
@ -438,13 +438,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
|
|||
if (data_port == pmac_ide[ix].regbase)
|
||||
break;
|
||||
|
||||
if (ix >= MAX_HWIFS) {
|
||||
/* Probably a PCI interface... */
|
||||
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i)
|
||||
hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET;
|
||||
hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
|
||||
return;
|
||||
}
|
||||
if (ix >= MAX_HWIFS)
|
||||
return; /* not an IDE PMAC interface */
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
hw->io_ports[i] = data_port + i * 0x10;
|
||||
|
@ -833,15 +828,8 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
tl[0] = *timings;
|
||||
tl[1] = *timings2;
|
||||
|
||||
switch(speed) {
|
||||
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
|
||||
case XFER_UDMA_6:
|
||||
case XFER_UDMA_5:
|
||||
case XFER_UDMA_4:
|
||||
case XFER_UDMA_3:
|
||||
case XFER_UDMA_2:
|
||||
case XFER_UDMA_1:
|
||||
case XFER_UDMA_0:
|
||||
if (speed >= XFER_UDMA_0) {
|
||||
if (pmif->kind == controller_kl_ata4)
|
||||
ret = set_timings_udma_ata4(&tl[0], speed);
|
||||
else if (pmif->kind == controller_un_ata6
|
||||
|
@ -850,21 +838,10 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
|||
else if (pmif->kind == controller_sh_ata6)
|
||||
ret = set_timings_udma_shasta(&tl[0], &tl[1], speed);
|
||||
else
|
||||
ret = 1;
|
||||
break;
|
||||
case XFER_MW_DMA_2:
|
||||
case XFER_MW_DMA_1:
|
||||
case XFER_MW_DMA_0:
|
||||
ret = -1;
|
||||
} else
|
||||
set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed);
|
||||
break;
|
||||
case XFER_SW_DMA_2:
|
||||
case XFER_SW_DMA_1:
|
||||
case XFER_SW_DMA_0:
|
||||
return;
|
||||
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
|
||||
default:
|
||||
ret = 1;
|
||||
}
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
|
|
|
@ -395,14 +395,12 @@ static int idescsi_expiry(ide_drive_t *drive)
|
|||
static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
|
||||
{
|
||||
idescsi_scsi_t *scsi = drive_to_idescsi(drive);
|
||||
idescsi_pc_t *pc=scsi->pc;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
idescsi_pc_t *pc = scsi->pc;
|
||||
struct request *rq = pc->rq;
|
||||
atapi_bcount_t bcount;
|
||||
atapi_status_t status;
|
||||
atapi_ireason_t ireason;
|
||||
atapi_feature_t feature;
|
||||
|
||||
unsigned int temp;
|
||||
u16 bcount;
|
||||
u8 stat, ireason;
|
||||
|
||||
#if IDESCSI_DEBUG_LOG
|
||||
printk (KERN_INFO "ide-scsi: Reached idescsi_pc_intr interrupt handler\n");
|
||||
|
@ -425,30 +423,29 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
|
|||
(void) HWIF(drive)->ide_dma_end(drive);
|
||||
}
|
||||
|
||||
feature.all = 0;
|
||||
/* Clear the interrupt */
|
||||
status.all = HWIF(drive)->INB(IDE_STATUS_REG);
|
||||
stat = drive->hwif->INB(IDE_STATUS_REG);
|
||||
|
||||
if (!status.b.drq) {
|
||||
if ((stat & DRQ_STAT) == 0) {
|
||||
/* No more interrupts */
|
||||
if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
|
||||
printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
|
||||
local_irq_enable_in_hardirq();
|
||||
if (status.b.check)
|
||||
if (stat & ERR_STAT)
|
||||
rq->errors++;
|
||||
idescsi_end_request (drive, 1, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG);
|
||||
bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG);
|
||||
ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
|
||||
bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
|
||||
hwif->INB(IDE_BCOUNTL_REG);
|
||||
ireason = hwif->INB(IDE_IREASON_REG);
|
||||
|
||||
if (ireason.b.cod) {
|
||||
if (ireason & CD) {
|
||||
printk(KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n");
|
||||
return ide_do_reset (drive);
|
||||
}
|
||||
if (ireason.b.io) {
|
||||
temp = pc->actually_transferred + bcount.all;
|
||||
if (ireason & IO) {
|
||||
temp = pc->actually_transferred + bcount;
|
||||
if (temp > pc->request_transfer) {
|
||||
if (temp > pc->buffer_size) {
|
||||
printk(KERN_ERR "ide-scsi: The scsi wants to "
|
||||
|
@ -461,11 +458,13 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
|
|||
idescsi_input_buffers(drive, pc, temp);
|
||||
else
|
||||
drive->hwif->atapi_input_bytes(drive, pc->current_position, temp);
|
||||
printk(KERN_ERR "ide-scsi: transferred %d of %d bytes\n", temp, bcount.all);
|
||||
printk(KERN_ERR "ide-scsi: transferred"
|
||||
" %d of %d bytes\n",
|
||||
temp, bcount);
|
||||
}
|
||||
pc->actually_transferred += temp;
|
||||
pc->current_position += temp;
|
||||
idescsi_discard_data(drive, bcount.all - temp);
|
||||
idescsi_discard_data(drive, bcount - temp);
|
||||
ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
|
||||
return ide_started;
|
||||
}
|
||||
|
@ -474,22 +473,24 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
|
|||
#endif /* IDESCSI_DEBUG_LOG */
|
||||
}
|
||||
}
|
||||
if (ireason.b.io) {
|
||||
if (ireason & IO) {
|
||||
clear_bit(PC_WRITING, &pc->flags);
|
||||
if (pc->sg)
|
||||
idescsi_input_buffers(drive, pc, bcount.all);
|
||||
idescsi_input_buffers(drive, pc, bcount);
|
||||
else
|
||||
HWIF(drive)->atapi_input_bytes(drive, pc->current_position, bcount.all);
|
||||
hwif->atapi_input_bytes(drive, pc->current_position,
|
||||
bcount);
|
||||
} else {
|
||||
set_bit(PC_WRITING, &pc->flags);
|
||||
if (pc->sg)
|
||||
idescsi_output_buffers (drive, pc, bcount.all);
|
||||
idescsi_output_buffers(drive, pc, bcount);
|
||||
else
|
||||
HWIF(drive)->atapi_output_bytes(drive, pc->current_position, bcount.all);
|
||||
hwif->atapi_output_bytes(drive, pc->current_position,
|
||||
bcount);
|
||||
}
|
||||
/* Update the current position */
|
||||
pc->actually_transferred += bcount.all;
|
||||
pc->current_position += bcount.all;
|
||||
pc->actually_transferred += bcount;
|
||||
pc->current_position += bcount;
|
||||
|
||||
/* And set the interrupt handler again */
|
||||
ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
|
||||
|
@ -501,16 +502,16 @@ 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_pc_t *pc = scsi->pc;
|
||||
atapi_ireason_t ireason;
|
||||
ide_startstop_t startstop;
|
||||
u8 ireason;
|
||||
|
||||
if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
|
||||
printk(KERN_ERR "ide-scsi: Strange, packet command "
|
||||
"initiated yet DRQ isn't asserted\n");
|
||||
return startstop;
|
||||
}
|
||||
ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
|
||||
if (!ireason.b.cod || ireason.b.io) {
|
||||
ireason = hwif->INB(IDE_IREASON_REG);
|
||||
if ((ireason & CD) == 0 || (ireason & IO)) {
|
||||
printk(KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while "
|
||||
"issuing a packet command\n");
|
||||
return ide_do_reset (drive);
|
||||
|
@ -573,30 +574,26 @@ static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc)
|
|||
{
|
||||
idescsi_scsi_t *scsi = drive_to_idescsi(drive);
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
atapi_feature_t feature;
|
||||
atapi_bcount_t bcount;
|
||||
u16 bcount;
|
||||
u8 dma = 0;
|
||||
|
||||
scsi->pc=pc; /* Set the current packet command */
|
||||
pc->actually_transferred=0; /* We haven't transferred any data yet */
|
||||
pc->current_position=pc->buffer;
|
||||
bcount.all = min(pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */
|
||||
/* Request to transfer the entire buffer at once */
|
||||
bcount = min(pc->request_transfer, 63 * 1024);
|
||||
|
||||
feature.all = 0;
|
||||
if (drive->using_dma && !idescsi_map_sg(drive, pc)) {
|
||||
hwif->sg_mapped = 1;
|
||||
feature.b.dma = !hwif->dma_setup(drive);
|
||||
dma = !hwif->dma_setup(drive);
|
||||
hwif->sg_mapped = 0;
|
||||
}
|
||||
|
||||
SELECT_DRIVE(drive);
|
||||
if (IDE_CONTROL_REG)
|
||||
HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
|
||||
|
||||
HWIF(drive)->OUTB(feature.all, IDE_FEATURE_REG);
|
||||
HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG);
|
||||
HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
|
||||
ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK, bcount, dma);
|
||||
|
||||
if (feature.b.dma)
|
||||
if (dma)
|
||||
set_bit(PC_DMA_OK, &pc->flags);
|
||||
|
||||
if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) {
|
||||
|
|
|
@ -89,11 +89,6 @@ static inline void ide_init_default_hwifs(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* some configuration options we don't need */
|
||||
|
||||
#undef SUPPORT_VLB_SYNC
|
||||
#define SUPPORT_VLB_SYNC 0
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __ASMCRIS_IDE_H */
|
||||
|
|
|
@ -48,11 +48,6 @@ static inline unsigned long ide_default_io_base(int index)
|
|||
return REG_TYPE_CONV(unsigned long, reg_ata_rw_ctrl2, ctrl2);
|
||||
}
|
||||
|
||||
/* some configuration options we don't need */
|
||||
|
||||
#undef SUPPORT_VLB_SYNC
|
||||
#define SUPPORT_VLB_SYNC 0
|
||||
|
||||
#define IDE_ARCH_ACK_INTR
|
||||
#define ide_ack_intr(hwif) ((hwif)->ack_intr(hwif))
|
||||
|
||||
|
|
|
@ -18,12 +18,6 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#undef SUPPORT_SLOW_DATA_PORTS
|
||||
#define SUPPORT_SLOW_DATA_PORTS 0
|
||||
|
||||
#undef SUPPORT_VLB_SYNC
|
||||
#define SUPPORT_VLB_SYNC 0
|
||||
|
||||
#ifndef MAX_HWIFS
|
||||
#define MAX_HWIFS 8
|
||||
#endif
|
||||
|
|
|
@ -42,9 +42,6 @@ struct ide_machdep_calls {
|
|||
|
||||
extern struct ide_machdep_calls ppc_ide_md;
|
||||
|
||||
#undef SUPPORT_SLOW_DATA_PORTS
|
||||
#define SUPPORT_SLOW_DATA_PORTS 0
|
||||
|
||||
#define IDE_ARCH_OBSOLETE_DEFAULTS
|
||||
|
||||
static __inline__ int ide_default_irq(unsigned long base)
|
||||
|
|
|
@ -144,7 +144,6 @@ enum rq_cmd_type_bits {
|
|||
* private REQ_LB opcodes to differentiate what type of request this is
|
||||
*/
|
||||
REQ_TYPE_ATA_CMD,
|
||||
REQ_TYPE_ATA_TASK,
|
||||
REQ_TYPE_ATA_TASKFILE,
|
||||
REQ_TYPE_ATA_PC,
|
||||
};
|
||||
|
|
|
@ -44,7 +44,9 @@
|
|||
|
||||
/* Bits for HD_ERROR */
|
||||
#define MARK_ERR 0x01 /* Bad address mark */
|
||||
#define ILI_ERR 0x01 /* Illegal Length Indication (ATAPI) */
|
||||
#define TRK0_ERR 0x02 /* couldn't find track 0 */
|
||||
#define EOM_ERR 0x02 /* End Of Media (ATAPI) */
|
||||
#define ABRT_ERR 0x04 /* Command aborted */
|
||||
#define MCR_ERR 0x08 /* media change request */
|
||||
#define ID_ERR 0x10 /* ID field not found */
|
||||
|
@ -52,6 +54,7 @@
|
|||
#define ECC_ERR 0x40 /* Uncorrectable ECC error */
|
||||
#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
|
||||
#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
|
||||
#define LFS_ERR 0xf0 /* Last Failed Sense (ATAPI) */
|
||||
|
||||
/* Bits of HD_NSECTOR */
|
||||
#define CD 0x01
|
||||
|
@ -70,13 +73,13 @@
|
|||
#define HDIO_DRIVE_HOB_HDR_SIZE (8 * sizeof(__u8))
|
||||
#define HDIO_DRIVE_TASK_HDR_SIZE (8 * sizeof(__u8))
|
||||
|
||||
#define IDE_DRIVE_TASK_INVALID -1
|
||||
#define IDE_DRIVE_TASK_NO_DATA 0
|
||||
#ifndef __KERNEL__
|
||||
#define IDE_DRIVE_TASK_INVALID -1
|
||||
#define IDE_DRIVE_TASK_SET_XFER 1
|
||||
|
||||
#define IDE_DRIVE_TASK_IN 2
|
||||
|
||||
#define IDE_DRIVE_TASK_OUT 3
|
||||
#endif
|
||||
#define IDE_DRIVE_TASK_RAW_WRITE 4
|
||||
|
||||
/*
|
||||
|
@ -87,10 +90,10 @@
|
|||
#ifndef __KERNEL__
|
||||
#define IDE_TASKFILE_STD_OUT_FLAGS 0xFE
|
||||
#define IDE_HOB_STD_OUT_FLAGS 0x3C
|
||||
#endif
|
||||
|
||||
typedef unsigned char task_ioreg_t;
|
||||
typedef unsigned long sata_ioreg_t;
|
||||
#endif
|
||||
|
||||
typedef union ide_reg_valid_s {
|
||||
unsigned all : 16;
|
||||
|
@ -116,8 +119,8 @@ typedef union ide_reg_valid_s {
|
|||
} ide_reg_valid_t;
|
||||
|
||||
typedef struct ide_task_request_s {
|
||||
task_ioreg_t io_ports[8];
|
||||
task_ioreg_t hob_ports[8];
|
||||
__u8 io_ports[8];
|
||||
__u8 hob_ports[8]; /* bytes 6 and 7 are unused */
|
||||
ide_reg_valid_t out_flags;
|
||||
ide_reg_valid_t in_flags;
|
||||
int data_phase;
|
||||
|
@ -133,36 +136,35 @@ typedef struct ide_ioctl_request_s {
|
|||
} ide_ioctl_request_t;
|
||||
|
||||
struct hd_drive_cmd_hdr {
|
||||
task_ioreg_t command;
|
||||
task_ioreg_t sector_number;
|
||||
task_ioreg_t feature;
|
||||
task_ioreg_t sector_count;
|
||||
__u8 command;
|
||||
__u8 sector_number;
|
||||
__u8 feature;
|
||||
__u8 sector_count;
|
||||
};
|
||||
|
||||
#ifndef __KERNEL__
|
||||
typedef struct hd_drive_task_hdr {
|
||||
task_ioreg_t data;
|
||||
task_ioreg_t feature;
|
||||
task_ioreg_t sector_count;
|
||||
task_ioreg_t sector_number;
|
||||
task_ioreg_t low_cylinder;
|
||||
task_ioreg_t high_cylinder;
|
||||
task_ioreg_t device_head;
|
||||
task_ioreg_t command;
|
||||
__u8 data;
|
||||
__u8 feature;
|
||||
__u8 sector_count;
|
||||
__u8 sector_number;
|
||||
__u8 low_cylinder;
|
||||
__u8 high_cylinder;
|
||||
__u8 device_head;
|
||||
__u8 command;
|
||||
} task_struct_t;
|
||||
|
||||
typedef struct hd_drive_hob_hdr {
|
||||
task_ioreg_t data;
|
||||
task_ioreg_t feature;
|
||||
task_ioreg_t sector_count;
|
||||
task_ioreg_t sector_number;
|
||||
task_ioreg_t low_cylinder;
|
||||
task_ioreg_t high_cylinder;
|
||||
task_ioreg_t device_head;
|
||||
task_ioreg_t control;
|
||||
__u8 data;
|
||||
__u8 feature;
|
||||
__u8 sector_count;
|
||||
__u8 sector_number;
|
||||
__u8 low_cylinder;
|
||||
__u8 high_cylinder;
|
||||
__u8 device_head;
|
||||
__u8 control;
|
||||
} hob_struct_t;
|
||||
|
||||
#define TASKFILE_INVALID 0x7fff
|
||||
#define TASKFILE_48 0x8000
|
||||
#endif
|
||||
|
||||
#define TASKFILE_NO_DATA 0x0000
|
||||
|
||||
|
@ -178,12 +180,16 @@ typedef struct hd_drive_hob_hdr {
|
|||
#define TASKFILE_IN_DMAQ 0x0080
|
||||
#define TASKFILE_OUT_DMAQ 0x0100
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#define TASKFILE_P_IN 0x0200
|
||||
#define TASKFILE_P_OUT 0x0400
|
||||
#define TASKFILE_P_IN_DMA 0x0800
|
||||
#define TASKFILE_P_OUT_DMA 0x1000
|
||||
#define TASKFILE_P_IN_DMAQ 0x2000
|
||||
#define TASKFILE_P_OUT_DMAQ 0x4000
|
||||
#define TASKFILE_48 0x8000
|
||||
#define TASKFILE_INVALID 0x7fff
|
||||
#endif
|
||||
|
||||
/* ATA/ATAPI Commands pre T13 Spec */
|
||||
#define WIN_NOP 0x00
|
||||
|
|
|
@ -27,25 +27,10 @@
|
|||
#include <asm/semaphore.h>
|
||||
#include <asm/mutex.h>
|
||||
|
||||
/******************************************************************************
|
||||
* IDE driver configuration options (play with these as desired):
|
||||
*
|
||||
* REALLY_SLOW_IO can be defined in ide.c and ide-cd.c, if necessary
|
||||
*/
|
||||
#define INITIAL_MULT_COUNT 0 /* off=0; on=2,4,8,16,32, etc.. */
|
||||
|
||||
#ifndef SUPPORT_SLOW_DATA_PORTS /* 1 to support slow data ports */
|
||||
#define SUPPORT_SLOW_DATA_PORTS 1 /* 0 to reduce kernel size */
|
||||
#endif
|
||||
#ifndef SUPPORT_VLB_SYNC /* 1 to support weird 32-bit chips */
|
||||
#define SUPPORT_VLB_SYNC 1 /* 0 to reduce kernel size */
|
||||
#endif
|
||||
#ifndef OK_TO_RESET_CONTROLLER /* 1 needed for good error recovery */
|
||||
#define OK_TO_RESET_CONTROLLER 1 /* 0 for use with AH2372A/B interface */
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_IRQ_NOSYNC
|
||||
#define DISABLE_IRQ_NOSYNC 0
|
||||
#if defined(CRIS) || defined(FRV)
|
||||
# define SUPPORT_VLB_SYNC 0
|
||||
#else
|
||||
# define SUPPORT_VLB_SYNC 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -55,10 +40,6 @@
|
|||
|
||||
#define IDE_NO_IRQ (-1)
|
||||
|
||||
/*
|
||||
* "No user-serviceable parts" beyond this point :)
|
||||
*****************************************************************************/
|
||||
|
||||
typedef unsigned char byte; /* used everywhere */
|
||||
|
||||
/*
|
||||
|
@ -103,8 +84,6 @@ typedef unsigned char byte; /* used everywhere */
|
|||
#define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET
|
||||
#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET
|
||||
|
||||
#define IDE_CONTROL_OFFSET_HOB (7)
|
||||
|
||||
#define IDE_DATA_REG (HWIF(drive)->io_ports[IDE_DATA_OFFSET])
|
||||
#define IDE_ERROR_REG (HWIF(drive)->io_ports[IDE_ERROR_OFFSET])
|
||||
#define IDE_NSECTOR_REG (HWIF(drive)->io_ports[IDE_NSECTOR_OFFSET])
|
||||
|
@ -327,46 +306,15 @@ static inline void ide_init_hwif_ports(hw_regs_t *hw,
|
|||
typedef union {
|
||||
unsigned all : 8;
|
||||
struct {
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
unsigned set_geometry : 1;
|
||||
unsigned recalibrate : 1;
|
||||
unsigned set_multmode : 1;
|
||||
unsigned set_tune : 1;
|
||||
unsigned serviced : 1;
|
||||
unsigned reserved : 3;
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
unsigned reserved : 3;
|
||||
unsigned serviced : 1;
|
||||
unsigned set_tune : 1;
|
||||
unsigned set_multmode : 1;
|
||||
unsigned recalibrate : 1;
|
||||
unsigned set_geometry : 1;
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
#endif
|
||||
} b;
|
||||
} special_t;
|
||||
|
||||
/*
|
||||
* ATA DATA Register Special.
|
||||
* ATA NSECTOR Count Register().
|
||||
* ATAPI Byte Count Register.
|
||||
*/
|
||||
typedef union {
|
||||
unsigned all :16;
|
||||
struct {
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
unsigned low :8; /* LSB */
|
||||
unsigned high :8; /* MSB */
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
unsigned high :8; /* MSB */
|
||||
unsigned low :8; /* LSB */
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
#endif
|
||||
} b;
|
||||
} ata_nsector_t, ata_data_t, atapi_bcount_t;
|
||||
|
||||
/*
|
||||
* ATA-IDE Select Register, aka Device-Head
|
||||
*
|
||||
|
@ -397,131 +345,6 @@ typedef union {
|
|||
} b;
|
||||
} select_t, ata_select_t;
|
||||
|
||||
/*
|
||||
* The ATA-IDE Status Register.
|
||||
* The ATAPI Status Register.
|
||||
*
|
||||
* check : Error occurred
|
||||
* idx : Index Error
|
||||
* corr : Correctable error occurred
|
||||
* drq : Data is request by the device
|
||||
* dsc : Disk Seek Complete : ata
|
||||
* : Media access command finished : atapi
|
||||
* df : Device Fault : ata
|
||||
* : Reserved : atapi
|
||||
* drdy : Ready, Command Mode Capable : ata
|
||||
* : Ignored for ATAPI commands : atapi
|
||||
* bsy : Disk is Busy
|
||||
* : The device has access to the command block
|
||||
*/
|
||||
typedef union {
|
||||
unsigned all :8;
|
||||
struct {
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
unsigned check :1;
|
||||
unsigned idx :1;
|
||||
unsigned corr :1;
|
||||
unsigned drq :1;
|
||||
unsigned dsc :1;
|
||||
unsigned df :1;
|
||||
unsigned drdy :1;
|
||||
unsigned bsy :1;
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
unsigned bsy :1;
|
||||
unsigned drdy :1;
|
||||
unsigned df :1;
|
||||
unsigned dsc :1;
|
||||
unsigned drq :1;
|
||||
unsigned corr :1;
|
||||
unsigned idx :1;
|
||||
unsigned check :1;
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
#endif
|
||||
} b;
|
||||
} ata_status_t, atapi_status_t;
|
||||
|
||||
/*
|
||||
* ATAPI Feature Register
|
||||
*
|
||||
* dma : Using DMA or PIO
|
||||
* reserved321 : Reserved
|
||||
* reserved654 : Reserved (Tag Type)
|
||||
* reserved7 : Reserved
|
||||
*/
|
||||
typedef union {
|
||||
unsigned all :8;
|
||||
struct {
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
unsigned dma :1;
|
||||
unsigned reserved321 :3;
|
||||
unsigned reserved654 :3;
|
||||
unsigned reserved7 :1;
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
unsigned reserved7 :1;
|
||||
unsigned reserved654 :3;
|
||||
unsigned reserved321 :3;
|
||||
unsigned dma :1;
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
#endif
|
||||
} b;
|
||||
} atapi_feature_t;
|
||||
|
||||
/*
|
||||
* ATAPI Interrupt Reason Register.
|
||||
*
|
||||
* cod : Information transferred is command (1) or data (0)
|
||||
* io : The device requests us to read (1) or write (0)
|
||||
* reserved : Reserved
|
||||
*/
|
||||
typedef union {
|
||||
unsigned all :8;
|
||||
struct {
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
unsigned cod :1;
|
||||
unsigned io :1;
|
||||
unsigned reserved :6;
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
unsigned reserved :6;
|
||||
unsigned io :1;
|
||||
unsigned cod :1;
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
#endif
|
||||
} b;
|
||||
} atapi_ireason_t;
|
||||
|
||||
/*
|
||||
* The ATAPI error register.
|
||||
*
|
||||
* ili : Illegal Length Indication
|
||||
* eom : End Of Media Detected
|
||||
* abrt : Aborted command - As defined by ATA
|
||||
* mcr : Media Change Requested - As defined by ATA
|
||||
* sense_key : Sense key of the last failed packet command
|
||||
*/
|
||||
typedef union {
|
||||
unsigned all :8;
|
||||
struct {
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
unsigned ili :1;
|
||||
unsigned eom :1;
|
||||
unsigned abrt :1;
|
||||
unsigned mcr :1;
|
||||
unsigned sense_key :4;
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
unsigned sense_key :4;
|
||||
unsigned mcr :1;
|
||||
unsigned abrt :1;
|
||||
unsigned eom :1;
|
||||
unsigned ili :1;
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
#endif
|
||||
} b;
|
||||
} atapi_error_t;
|
||||
|
||||
/*
|
||||
* Status returned from various ide_ functions
|
||||
*/
|
||||
|
@ -701,8 +524,6 @@ typedef struct hwif_s {
|
|||
void (*pre_reset)(ide_drive_t *);
|
||||
/* routine to reset controller after a disk reset */
|
||||
void (*resetproc)(ide_drive_t *);
|
||||
/* special interrupt handling for shared pci interrupts */
|
||||
void (*intrproc)(ide_drive_t *);
|
||||
/* special host masking for drive selection */
|
||||
void (*maskproc)(ide_drive_t *, int);
|
||||
/* check host's drive quirk list */
|
||||
|
@ -766,7 +587,6 @@ typedef struct hwif_s {
|
|||
int rqsize; /* max sectors per request */
|
||||
int irq; /* our irq number */
|
||||
|
||||
unsigned long dma_master; /* reference base addr dmabase */
|
||||
unsigned long dma_base; /* base addr for dma ports */
|
||||
unsigned long dma_command; /* dma command register */
|
||||
unsigned long dma_vendor1; /* dma vendor 1 register */
|
||||
|
@ -806,7 +626,6 @@ typedef struct hwif_s {
|
|||
/*
|
||||
* internal ide interrupt handler type
|
||||
*/
|
||||
typedef ide_startstop_t (ide_pre_handler_t)(ide_drive_t *, struct request *);
|
||||
typedef ide_startstop_t (ide_handler_t)(ide_drive_t *);
|
||||
typedef int (ide_expiry_t)(ide_drive_t *);
|
||||
|
||||
|
@ -1020,7 +839,8 @@ int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
|
|||
|
||||
extern void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry);
|
||||
|
||||
extern void ide_execute_command(ide_drive_t *, task_ioreg_t cmd, ide_handler_t *, unsigned int, ide_expiry_t *);
|
||||
void ide_execute_command(ide_drive_t *, u8, ide_handler_t *, unsigned int,
|
||||
ide_expiry_t *);
|
||||
|
||||
ide_startstop_t __ide_error(ide_drive_t *, struct request *, u8, u8);
|
||||
|
||||
|
@ -1062,52 +882,114 @@ extern void ide_end_drive_cmd(ide_drive_t *, u8, u8);
|
|||
*/
|
||||
extern int ide_wait_cmd(ide_drive_t *, u8, u8, u8, u8, u8 *);
|
||||
|
||||
enum {
|
||||
IDE_TFLAG_LBA48 = (1 << 0),
|
||||
IDE_TFLAG_NO_SELECT_MASK = (1 << 1),
|
||||
IDE_TFLAG_FLAGGED = (1 << 2),
|
||||
IDE_TFLAG_OUT_DATA = (1 << 3),
|
||||
IDE_TFLAG_OUT_HOB_FEATURE = (1 << 4),
|
||||
IDE_TFLAG_OUT_HOB_NSECT = (1 << 5),
|
||||
IDE_TFLAG_OUT_HOB_LBAL = (1 << 6),
|
||||
IDE_TFLAG_OUT_HOB_LBAM = (1 << 7),
|
||||
IDE_TFLAG_OUT_HOB_LBAH = (1 << 8),
|
||||
IDE_TFLAG_OUT_HOB = IDE_TFLAG_OUT_HOB_FEATURE |
|
||||
IDE_TFLAG_OUT_HOB_NSECT |
|
||||
IDE_TFLAG_OUT_HOB_LBAL |
|
||||
IDE_TFLAG_OUT_HOB_LBAM |
|
||||
IDE_TFLAG_OUT_HOB_LBAH,
|
||||
IDE_TFLAG_OUT_FEATURE = (1 << 9),
|
||||
IDE_TFLAG_OUT_NSECT = (1 << 10),
|
||||
IDE_TFLAG_OUT_LBAL = (1 << 11),
|
||||
IDE_TFLAG_OUT_LBAM = (1 << 12),
|
||||
IDE_TFLAG_OUT_LBAH = (1 << 13),
|
||||
IDE_TFLAG_OUT_TF = IDE_TFLAG_OUT_FEATURE |
|
||||
IDE_TFLAG_OUT_NSECT |
|
||||
IDE_TFLAG_OUT_LBAL |
|
||||
IDE_TFLAG_OUT_LBAM |
|
||||
IDE_TFLAG_OUT_LBAH,
|
||||
IDE_TFLAG_OUT_DEVICE = (1 << 14),
|
||||
IDE_TFLAG_WRITE = (1 << 15),
|
||||
IDE_TFLAG_FLAGGED_SET_IN_FLAGS = (1 << 16),
|
||||
IDE_TFLAG_IN_DATA = (1 << 17),
|
||||
IDE_TFLAG_CUSTOM_HANDLER = (1 << 18),
|
||||
IDE_TFLAG_DMA_PIO_FALLBACK = (1 << 19),
|
||||
IDE_TFLAG_IN_HOB_FEATURE = (1 << 20),
|
||||
IDE_TFLAG_IN_HOB_NSECT = (1 << 21),
|
||||
IDE_TFLAG_IN_HOB_LBAL = (1 << 22),
|
||||
IDE_TFLAG_IN_HOB_LBAM = (1 << 23),
|
||||
IDE_TFLAG_IN_HOB_LBAH = (1 << 24),
|
||||
IDE_TFLAG_IN_HOB_LBA = IDE_TFLAG_IN_HOB_LBAL |
|
||||
IDE_TFLAG_IN_HOB_LBAM |
|
||||
IDE_TFLAG_IN_HOB_LBAH,
|
||||
IDE_TFLAG_IN_HOB = IDE_TFLAG_IN_HOB_FEATURE |
|
||||
IDE_TFLAG_IN_HOB_NSECT |
|
||||
IDE_TFLAG_IN_HOB_LBA,
|
||||
IDE_TFLAG_IN_NSECT = (1 << 25),
|
||||
IDE_TFLAG_IN_LBAL = (1 << 26),
|
||||
IDE_TFLAG_IN_LBAM = (1 << 27),
|
||||
IDE_TFLAG_IN_LBAH = (1 << 28),
|
||||
IDE_TFLAG_IN_LBA = IDE_TFLAG_IN_LBAL |
|
||||
IDE_TFLAG_IN_LBAM |
|
||||
IDE_TFLAG_IN_LBAH,
|
||||
IDE_TFLAG_IN_TF = IDE_TFLAG_IN_NSECT |
|
||||
IDE_TFLAG_IN_LBA,
|
||||
IDE_TFLAG_IN_DEVICE = (1 << 29),
|
||||
};
|
||||
|
||||
struct ide_taskfile {
|
||||
u8 hob_data; /* 0: high data byte (for TASKFILE IOCTL) */
|
||||
|
||||
u8 hob_feature; /* 1-5: additional data to support LBA48 */
|
||||
u8 hob_nsect;
|
||||
u8 hob_lbal;
|
||||
u8 hob_lbam;
|
||||
u8 hob_lbah;
|
||||
|
||||
u8 data; /* 6: low data byte (for TASKFILE IOCTL) */
|
||||
|
||||
union { /* 7: */
|
||||
u8 error; /* read: error */
|
||||
u8 feature; /* write: feature */
|
||||
};
|
||||
|
||||
u8 nsect; /* 8: number of sectors */
|
||||
u8 lbal; /* 9: LBA low */
|
||||
u8 lbam; /* 10: LBA mid */
|
||||
u8 lbah; /* 11: LBA high */
|
||||
|
||||
u8 device; /* 12: device select */
|
||||
|
||||
union { /* 13: */
|
||||
u8 status; /* read: status */
|
||||
u8 command; /* write: command */
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct ide_task_s {
|
||||
/*
|
||||
* struct hd_drive_task_hdr tf;
|
||||
* task_struct_t tf;
|
||||
* struct hd_drive_hob_hdr hobf;
|
||||
* hob_struct_t hobf;
|
||||
*/
|
||||
task_ioreg_t tfRegister[8];
|
||||
task_ioreg_t hobRegister[8];
|
||||
ide_reg_valid_t tf_out_flags;
|
||||
ide_reg_valid_t tf_in_flags;
|
||||
union {
|
||||
struct ide_taskfile tf;
|
||||
u8 tf_array[14];
|
||||
};
|
||||
u32 tf_flags;
|
||||
int data_phase;
|
||||
int command_type;
|
||||
ide_pre_handler_t *prehandler;
|
||||
ide_handler_t *handler;
|
||||
struct request *rq; /* copy of request */
|
||||
void *special; /* valid_t generally */
|
||||
} ide_task_t;
|
||||
|
||||
extern u32 ide_read_24(ide_drive_t *);
|
||||
void ide_tf_load(ide_drive_t *, ide_task_t *);
|
||||
void ide_tf_read(ide_drive_t *, ide_task_t *);
|
||||
|
||||
extern void SELECT_DRIVE(ide_drive_t *);
|
||||
extern void SELECT_INTERRUPT(ide_drive_t *);
|
||||
extern void SELECT_MASK(ide_drive_t *, int);
|
||||
extern void QUIRK_LIST(ide_drive_t *);
|
||||
|
||||
extern int drive_is_ready(ide_drive_t *);
|
||||
|
||||
/*
|
||||
* taskfile io for disks for now...and builds request from ide_ioctl
|
||||
*/
|
||||
extern ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *);
|
||||
void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8);
|
||||
|
||||
/*
|
||||
* Special Flagged Register Validation Caller
|
||||
*/
|
||||
extern ide_startstop_t flagged_taskfile(ide_drive_t *, ide_task_t *);
|
||||
ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *);
|
||||
|
||||
extern ide_startstop_t set_multmode_intr(ide_drive_t *);
|
||||
extern ide_startstop_t set_geometry_intr(ide_drive_t *);
|
||||
extern ide_startstop_t recal_intr(ide_drive_t *);
|
||||
extern ide_startstop_t task_no_data_intr(ide_drive_t *);
|
||||
extern ide_startstop_t task_in_intr(ide_drive_t *);
|
||||
extern ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
|
||||
|
||||
extern int ide_raw_taskfile(ide_drive_t *, ide_task_t *, u8 *);
|
||||
int ide_raw_taskfile(ide_drive_t *, ide_task_t *, u8 *, u16);
|
||||
int ide_no_data_taskfile(ide_drive_t *, ide_task_t *);
|
||||
|
||||
int ide_taskfile_ioctl(ide_drive_t *, unsigned int, unsigned long);
|
||||
int ide_cmd_ioctl(ide_drive_t *, unsigned int, unsigned long);
|
||||
|
@ -1212,6 +1094,7 @@ enum {
|
|||
IDE_HFLAG_IO_32BIT = (1 << 24),
|
||||
/* unmask IRQs */
|
||||
IDE_HFLAG_UNMASK_IRQS = (1 << 25),
|
||||
IDE_HFLAG_ABUSE_SET_DMA_MODE = (1 << 26),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_OFFBOARD
|
||||
|
@ -1229,7 +1112,7 @@ struct ide_port_info {
|
|||
void (*fixup)(ide_hwif_t *);
|
||||
ide_pci_enablebit_t enablebits[2];
|
||||
hwif_chipset_t chipset;
|
||||
unsigned int extra;
|
||||
u8 extra;
|
||||
u32 host_flags;
|
||||
u8 pio_mask;
|
||||
u8 swdma_mask;
|
||||
|
@ -1356,6 +1239,7 @@ static inline int ide_dev_is_sata(struct hd_driveid *id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u64 ide_get_lba_addr(struct ide_taskfile *, int);
|
||||
u8 ide_dump_status(ide_drive_t *, const char *, u8);
|
||||
|
||||
typedef struct ide_pio_timings_s {
|
||||
|
|
Загрузка…
Ссылка в новой задаче