Disable PortMultiplier Async Notifications for time of ports reset.

They are useless at that time, but confuse Marvell AHCI.

Add quirk for SiI57XX Port Multipliers, to hide extra port.
This commit is contained in:
Alexander Motin 2009-11-16 15:18:02 +00:00
parent 11ea9440c3
commit 3a3e47990c

View File

@ -63,11 +63,12 @@ __FBSDID("$FreeBSD$");
typedef enum {
PMP_STATE_NORMAL,
PMP_STATE_PORTS,
PMP_STATE_CONFIG,
PMP_STATE_PRECONFIG,
PMP_STATE_RESET,
PMP_STATE_CONNECT,
PMP_STATE_CHECK,
PMP_STATE_CLEAR,
PMP_STATE_CONFIG,
PMP_STATE_SCAN
} pmp_state;
@ -436,7 +437,7 @@ pmpstart(struct cam_periph *periph, union ccb *start_ccb)
pmp_default_timeout * 1000);
ata_pm_read_cmd(ataio, 2, 15);
break;
case PMP_STATE_CONFIG:
case PMP_STATE_PRECONFIG:
cam_fill_ataio(ataio,
pmp_retry_count,
pmpdone,
@ -445,7 +446,7 @@ pmpstart(struct cam_periph *periph, union ccb *start_ccb)
/*data_ptr*/NULL,
/*dxfer_len*/0,
pmp_default_timeout * 1000);
ata_pm_write_cmd(ataio, 0x60, 15, 0xf);
ata_pm_write_cmd(ataio, 0x60, 15, 0x0);
break;
case PMP_STATE_RESET:
cam_fill_ataio(ataio,
@ -495,6 +496,17 @@ printf("PM RESET %d%s\n", softc->pm_step,
pmp_default_timeout * 1000);
ata_pm_write_cmd(ataio, 1, softc->pm_step, 0xFFFFFFFF);
break;
case PMP_STATE_CONFIG:
cam_fill_ataio(ataio,
pmp_retry_count,
pmpdone,
/*flags*/CAM_DIR_NONE,
0,
/*data_ptr*/NULL,
/*dxfer_len*/0,
pmp_default_timeout * 1000);
ata_pm_write_cmd(ataio, 0x60, 15, 0xf);
break;
default:
break;
}
@ -554,24 +566,29 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
(done_ccb->ataio.res.lba_mid << 16) +
(done_ccb->ataio.res.lba_low << 8) +
done_ccb->ataio.res.sector_count;
/* This PM declares 6 ports, while only 5 of them are real.
/* This PMP declares 6 ports, while only 5 of them are real.
* Port 5 is enclosure management bridge port, which has implementation
* problems, causing probe faults. Hide it for now. */
if (softc->pm_pid == 0x37261095 && softc->pm_ports == 6)
softc->pm_ports = 5;
/* This PM declares 7 ports, while only 5 of them are real.
/* This PMP declares 7 ports, while only 5 of them are real.
* Port 5 is some fake "Config Disk" with 640 sectors size,
* port 6 is enclosure management bridge port.
* Both fake ports has implementation problems, causing
* probe faults. Hide them for now. */
if (softc->pm_pid == 0x47261095 && softc->pm_ports == 7)
softc->pm_ports = 5;
/* These PMPs declare one more port then actually have,
* for configuration purposes. Hide it for now. */
if (softc->pm_pid == 0x57231095 || softc->pm_pid == 0x57331095 ||
softc->pm_pid == 0x57341095 || softc->pm_pid == 0x57441095)
softc->pm_ports--;
printf("PM ports: %d\n", softc->pm_ports);
softc->state = PMP_STATE_CONFIG;
softc->state = PMP_STATE_PRECONFIG;
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
return;
case PMP_STATE_CONFIG:
case PMP_STATE_PRECONFIG:
softc->pm_step = 0;
softc->state = PMP_STATE_RESET;
softc->reset |= ~softc->found;
@ -658,11 +675,15 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
return;
case PMP_STATE_CLEAR:
softc->pm_step++;
if (softc->pm_step < softc->pm_ports) {
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
return;
} else if (softc->found) {
if (softc->pm_step >= softc->pm_ports) {
softc->state = PMP_STATE_CONFIG;
softc->pm_step = 0;
}
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
return;
case PMP_STATE_CONFIG:
if (softc->found) {
softc->pm_step = 0;
softc->state = PMP_STATE_SCAN;
work_ccb = xpt_alloc_ccb_nowait();