Skip to content

Commit f343e57

Browse files
Ondrej Zarydamien-lemoal
authored andcommitted
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 <[email protected]> Reviewed-by: Sergey Shtylyov <[email protected]> Signed-off-by: Damien Le Moal <[email protected]>
1 parent d230242 commit f343e57

File tree

1 file changed

+67
-1
lines changed

1 file changed

+67
-1
lines changed

drivers/ata/pata_parport/pata_parport.c

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,72 @@ static bool pata_parport_devchk(struct ata_port *ap, unsigned int device)
8080
return (nsect == 0x55) && (lbal == 0xaa);
8181
}
8282

83+
static int pata_parport_wait_after_reset(struct ata_link *link,
84+
unsigned int devmask,
85+
unsigned long deadline)
86+
{
87+
struct ata_port *ap = link->ap;
88+
struct pi_adapter *pi = ap->host->private_data;
89+
unsigned int dev0 = devmask & (1 << 0);
90+
unsigned int dev1 = devmask & (1 << 1);
91+
int rc, ret = 0;
92+
93+
ata_msleep(ap, ATA_WAIT_AFTER_RESET);
94+
95+
/* always check readiness of the master device */
96+
rc = ata_sff_wait_ready(link, deadline);
97+
if (rc) {
98+
/*
99+
* some adapters return bogus values if master device is not
100+
* present, so don't abort now if a slave device is present
101+
*/
102+
if (!dev1)
103+
return rc;
104+
ret = -ENODEV;
105+
}
106+
107+
/*
108+
* if device 1 was found in ata_devchk, wait for register
109+
* access briefly, then wait for BSY to clear.
110+
*/
111+
if (dev1) {
112+
int i;
113+
114+
pata_parport_dev_select(ap, 1);
115+
116+
/*
117+
* Wait for register access. Some ATAPI devices fail
118+
* to set nsect/lbal after reset, so don't waste too
119+
* much time on it. We're gonna wait for !BSY anyway.
120+
*/
121+
for (i = 0; i < 2; i++) {
122+
u8 nsect, lbal;
123+
124+
nsect = pi->proto->read_regr(pi, 0, ATA_REG_NSECT);
125+
lbal = pi->proto->read_regr(pi, 0, ATA_REG_LBAL);
126+
if (nsect == 1 && lbal == 1)
127+
break;
128+
/* give drive a breather */
129+
ata_msleep(ap, 50);
130+
}
131+
132+
rc = ata_sff_wait_ready(link, deadline);
133+
if (rc) {
134+
if (rc != -ENODEV)
135+
return rc;
136+
ret = rc;
137+
}
138+
}
139+
140+
pata_parport_dev_select(ap, 0);
141+
if (dev1)
142+
pata_parport_dev_select(ap, 1);
143+
if (dev0)
144+
pata_parport_dev_select(ap, 0);
145+
146+
return ret;
147+
}
148+
83149
static int pata_parport_bus_softreset(struct ata_port *ap, unsigned int devmask,
84150
unsigned long deadline)
85151
{
@@ -94,7 +160,7 @@ static int pata_parport_bus_softreset(struct ata_port *ap, unsigned int devmask,
94160
ap->last_ctl = ap->ctl;
95161

96162
/* wait the port to become ready */
97-
return ata_sff_wait_after_reset(&ap->link, devmask, deadline);
163+
return pata_parport_wait_after_reset(&ap->link, devmask, deadline);
98164
}
99165

100166
static int pata_parport_softreset(struct ata_link *link, unsigned int *classes,

0 commit comments

Comments
 (0)