mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-12 05:24:12 +08:00
ata: pata_parport: add custom version of wait_after_reset
Some parallel adapters (e.g. EXP Computer MC-1285B EPP Cable) return bogus values when there's no master device present. This can cause reset to fail, preventing the lone slave device (such as EXP Computer CD-865) from working. Add custom version of wait_after_reset that ignores master failure when a slave device is present. The custom version is also needed because the generic ata_sff_wait_after_reset uses direct port I/O for slave device detection. Signed-off-by: Ondrej Zary <linux@zary.sk> Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
This commit is contained in:
parent
d2302427c1
commit
f343e578fe
@ -80,6 +80,72 @@ static bool pata_parport_devchk(struct ata_port *ap, unsigned int device)
|
||||
return (nsect == 0x55) && (lbal == 0xaa);
|
||||
}
|
||||
|
||||
static int pata_parport_wait_after_reset(struct ata_link *link,
|
||||
unsigned int devmask,
|
||||
unsigned long deadline)
|
||||
{
|
||||
struct ata_port *ap = link->ap;
|
||||
struct pi_adapter *pi = ap->host->private_data;
|
||||
unsigned int dev0 = devmask & (1 << 0);
|
||||
unsigned int dev1 = devmask & (1 << 1);
|
||||
int rc, ret = 0;
|
||||
|
||||
ata_msleep(ap, ATA_WAIT_AFTER_RESET);
|
||||
|
||||
/* always check readiness of the master device */
|
||||
rc = ata_sff_wait_ready(link, deadline);
|
||||
if (rc) {
|
||||
/*
|
||||
* some adapters return bogus values if master device is not
|
||||
* present, so don't abort now if a slave device is present
|
||||
*/
|
||||
if (!dev1)
|
||||
return rc;
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* if device 1 was found in ata_devchk, wait for register
|
||||
* access briefly, then wait for BSY to clear.
|
||||
*/
|
||||
if (dev1) {
|
||||
int i;
|
||||
|
||||
pata_parport_dev_select(ap, 1);
|
||||
|
||||
/*
|
||||
* Wait for register access. Some ATAPI devices fail
|
||||
* to set nsect/lbal after reset, so don't waste too
|
||||
* much time on it. We're gonna wait for !BSY anyway.
|
||||
*/
|
||||
for (i = 0; i < 2; i++) {
|
||||
u8 nsect, lbal;
|
||||
|
||||
nsect = pi->proto->read_regr(pi, 0, ATA_REG_NSECT);
|
||||
lbal = pi->proto->read_regr(pi, 0, ATA_REG_LBAL);
|
||||
if (nsect == 1 && lbal == 1)
|
||||
break;
|
||||
/* give drive a breather */
|
||||
ata_msleep(ap, 50);
|
||||
}
|
||||
|
||||
rc = ata_sff_wait_ready(link, deadline);
|
||||
if (rc) {
|
||||
if (rc != -ENODEV)
|
||||
return rc;
|
||||
ret = rc;
|
||||
}
|
||||
}
|
||||
|
||||
pata_parport_dev_select(ap, 0);
|
||||
if (dev1)
|
||||
pata_parport_dev_select(ap, 1);
|
||||
if (dev0)
|
||||
pata_parport_dev_select(ap, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pata_parport_bus_softreset(struct ata_port *ap, unsigned int devmask,
|
||||
unsigned long deadline)
|
||||
{
|
||||
@ -94,7 +160,7 @@ static int pata_parport_bus_softreset(struct ata_port *ap, unsigned int devmask,
|
||||
ap->last_ctl = ap->ctl;
|
||||
|
||||
/* wait the port to become ready */
|
||||
return ata_sff_wait_after_reset(&ap->link, devmask, deadline);
|
||||
return pata_parport_wait_after_reset(&ap->link, devmask, deadline);
|
||||
}
|
||||
|
||||
static int pata_parport_softreset(struct ata_link *link, unsigned int *classes,
|
||||
|
Loading…
Reference in New Issue
Block a user