113014ca0SSøren Schmidt /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
49a14aa01SUlrich Spörlein * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
513014ca0SSøren Schmidt * All rights reserved.
613014ca0SSøren Schmidt *
713014ca0SSøren Schmidt * Redistribution and use in source and binary forms, with or without
813014ca0SSøren Schmidt * modification, are permitted provided that the following conditions
913014ca0SSøren Schmidt * are met:
1013014ca0SSøren Schmidt * 1. Redistributions of source code must retain the above copyright
1113014ca0SSøren Schmidt * notice, this list of conditions and the following disclaimer,
1213014ca0SSøren Schmidt * without modification, immediately at the beginning of the file.
1313014ca0SSøren Schmidt * 2. Redistributions in binary form must reproduce the above copyright
1413014ca0SSøren Schmidt * notice, this list of conditions and the following disclaimer in the
1513014ca0SSøren Schmidt * documentation and/or other materials provided with the distribution.
1613014ca0SSøren Schmidt *
1713014ca0SSøren Schmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1813014ca0SSøren Schmidt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1913014ca0SSøren Schmidt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2013014ca0SSøren Schmidt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2113014ca0SSøren Schmidt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2213014ca0SSøren Schmidt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2313014ca0SSøren Schmidt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2413014ca0SSøren Schmidt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2513014ca0SSøren Schmidt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2613014ca0SSøren Schmidt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2713014ca0SSøren Schmidt */
2813014ca0SSøren Schmidt
2913014ca0SSøren Schmidt #include <sys/param.h>
3013014ca0SSøren Schmidt #include <sys/systm.h>
3113014ca0SSøren Schmidt #include <sys/kernel.h>
3213014ca0SSøren Schmidt #include <sys/ata.h>
3313014ca0SSøren Schmidt #include <sys/bus.h>
3413014ca0SSøren Schmidt #include <sys/endian.h>
3513014ca0SSøren Schmidt #include <sys/malloc.h>
3613014ca0SSøren Schmidt #include <sys/lock.h>
3713014ca0SSøren Schmidt #include <sys/mutex.h>
3813014ca0SSøren Schmidt #include <sys/sema.h>
3913014ca0SSøren Schmidt #include <sys/taskqueue.h>
4013014ca0SSøren Schmidt #include <vm/uma.h>
4113014ca0SSøren Schmidt #include <machine/stdarg.h>
4213014ca0SSøren Schmidt #include <machine/resource.h>
4313014ca0SSøren Schmidt #include <machine/bus.h>
4413014ca0SSøren Schmidt #include <sys/rman.h>
4513014ca0SSøren Schmidt #include <dev/ata/ata-all.h>
4613014ca0SSøren Schmidt #include <ata_if.h>
4713014ca0SSøren Schmidt
4813014ca0SSøren Schmidt void
ata_sata_phy_check_events(device_t dev,int port)49bda55b6aSAlexander Motin ata_sata_phy_check_events(device_t dev, int port)
5013014ca0SSøren Schmidt {
5113014ca0SSøren Schmidt struct ata_channel *ch = device_get_softc(dev);
52bda55b6aSAlexander Motin u_int32_t error, status;
5313014ca0SSøren Schmidt
54f5d569f3SAlexander Motin if (ata_sata_scr_read(ch, port, ATA_SERROR, &error))
55f5d569f3SAlexander Motin return;
560eac2d6bSAlexander Motin
570eac2d6bSAlexander Motin /* Check that SError value is sane. */
580eac2d6bSAlexander Motin if (error == 0xffffffff)
590eac2d6bSAlexander Motin return;
600eac2d6bSAlexander Motin
61bda55b6aSAlexander Motin /* Clear set error bits/interrupt. */
62bda55b6aSAlexander Motin if (error)
63bda55b6aSAlexander Motin ata_sata_scr_write(ch, port, ATA_SERROR, error);
6413014ca0SSøren Schmidt
6513014ca0SSøren Schmidt /* if we have a connection event deal with it */
664c10f2e6SAlexander Motin if ((error & ATA_SE_PHY_CHANGED) && (ch->pm_level == 0)) {
676030a3f0SAlexander Motin if (bootverbose) {
68f5d569f3SAlexander Motin if (ata_sata_scr_read(ch, port, ATA_SSTATUS, &status)) {
69f5d569f3SAlexander Motin device_printf(dev, "PHYRDY change\n");
70f5d569f3SAlexander Motin } else if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
71bda55b6aSAlexander Motin ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
72bda55b6aSAlexander Motin ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) {
7313014ca0SSøren Schmidt device_printf(dev, "CONNECT requested\n");
746030a3f0SAlexander Motin } else
7513014ca0SSøren Schmidt device_printf(dev, "DISCONNECT requested\n");
7613014ca0SSøren Schmidt }
776030a3f0SAlexander Motin taskqueue_enqueue(taskqueue_thread, &ch->conntask);
7813014ca0SSøren Schmidt }
7913014ca0SSøren Schmidt }
8013014ca0SSøren Schmidt
819cf4fe2eSAlexander Motin int
ata_sata_scr_read(struct ata_channel * ch,int port,int reg,uint32_t * val)829cf4fe2eSAlexander Motin ata_sata_scr_read(struct ata_channel *ch, int port, int reg, uint32_t *val)
839cf4fe2eSAlexander Motin {
849cf4fe2eSAlexander Motin
85bda55b6aSAlexander Motin if (ch->hw.pm_read != NULL)
86bda55b6aSAlexander Motin return (ch->hw.pm_read(ch->dev, port, reg, val));
87bda55b6aSAlexander Motin if (ch->r_io[reg].res) {
889cf4fe2eSAlexander Motin *val = ATA_IDX_INL(ch, reg);
899cf4fe2eSAlexander Motin return (0);
909cf4fe2eSAlexander Motin }
91bda55b6aSAlexander Motin return (-1);
929cf4fe2eSAlexander Motin }
939cf4fe2eSAlexander Motin
949cf4fe2eSAlexander Motin int
ata_sata_scr_write(struct ata_channel * ch,int port,int reg,uint32_t val)959cf4fe2eSAlexander Motin ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val)
969cf4fe2eSAlexander Motin {
979cf4fe2eSAlexander Motin
98bda55b6aSAlexander Motin if (ch->hw.pm_write != NULL)
99bda55b6aSAlexander Motin return (ch->hw.pm_write(ch->dev, port, reg, val));
100bda55b6aSAlexander Motin if (ch->r_io[reg].res) {
1019cf4fe2eSAlexander Motin ATA_IDX_OUTL(ch, reg, val);
1029cf4fe2eSAlexander Motin return (0);
1039cf4fe2eSAlexander Motin }
104bda55b6aSAlexander Motin return (-1);
1059cf4fe2eSAlexander Motin }
1069cf4fe2eSAlexander Motin
10713014ca0SSøren Schmidt static int
ata_sata_connect(struct ata_channel * ch,int port,int quick)108bda55b6aSAlexander Motin ata_sata_connect(struct ata_channel *ch, int port, int quick)
10913014ca0SSøren Schmidt {
11013014ca0SSøren Schmidt u_int32_t status;
111bda55b6aSAlexander Motin int timeout, t;
11213014ca0SSøren Schmidt
11313014ca0SSøren Schmidt /* wait up to 1 second for "connect well" */
114bda55b6aSAlexander Motin timeout = (quick == 2) ? 0 : 100;
115bda55b6aSAlexander Motin t = 0;
116bda55b6aSAlexander Motin while (1) {
1179cf4fe2eSAlexander Motin if (ata_sata_scr_read(ch, port, ATA_SSTATUS, &status))
1189cf4fe2eSAlexander Motin return (0);
119bda55b6aSAlexander Motin if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
120bda55b6aSAlexander Motin ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
121bda55b6aSAlexander Motin ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE))
122bda55b6aSAlexander Motin break;
123bda55b6aSAlexander Motin if (++t > timeout)
12413014ca0SSøren Schmidt break;
12513014ca0SSøren Schmidt ata_udelay(10000);
12613014ca0SSøren Schmidt }
1279cf4fe2eSAlexander Motin if (bootverbose) {
128bda55b6aSAlexander Motin if (t > timeout) {
1299cf4fe2eSAlexander Motin if (port < 0) {
1309cf4fe2eSAlexander Motin device_printf(ch->dev, "SATA connect timeout status=%08x\n",
1319cf4fe2eSAlexander Motin status);
1329cf4fe2eSAlexander Motin } else {
1339cf4fe2eSAlexander Motin device_printf(ch->dev, "p%d: SATA connect timeout status=%08x\n",
1349cf4fe2eSAlexander Motin port, status);
1359cf4fe2eSAlexander Motin }
136bda55b6aSAlexander Motin } else if (port < 0) {
1379cf4fe2eSAlexander Motin device_printf(ch->dev, "SATA connect time=%dms status=%08x\n",
138bda55b6aSAlexander Motin t * 10, status);
1399cf4fe2eSAlexander Motin } else {
1409cf4fe2eSAlexander Motin device_printf(ch->dev, "p%d: SATA connect time=%dms status=%08x\n",
141bda55b6aSAlexander Motin port, t * 10, status);
1429cf4fe2eSAlexander Motin }
1439cf4fe2eSAlexander Motin }
14413014ca0SSøren Schmidt
14513014ca0SSøren Schmidt /* clear SATA error register */
1469cf4fe2eSAlexander Motin ata_sata_scr_write(ch, port, ATA_SERROR, 0xffffffff);
14713014ca0SSøren Schmidt
148bda55b6aSAlexander Motin return ((t > timeout) ? 0 : 1);
14913014ca0SSøren Schmidt }
15013014ca0SSøren Schmidt
15113014ca0SSøren Schmidt int
ata_sata_phy_reset(device_t dev,int port,int quick)1529cf4fe2eSAlexander Motin ata_sata_phy_reset(device_t dev, int port, int quick)
15313014ca0SSøren Schmidt {
15413014ca0SSøren Schmidt struct ata_channel *ch = device_get_softc(dev);
1559c87d811SAlexander Motin int loop, retry, sata_rev;
1569c87d811SAlexander Motin uint32_t val, val1;
1579c87d811SAlexander Motin
1589c87d811SAlexander Motin sata_rev = ch->user[port < 0 ? 0 : port].revision;
1599c87d811SAlexander Motin if (sata_rev > 0)
1609c87d811SAlexander Motin quick = 0;
16113014ca0SSøren Schmidt
1629cf4fe2eSAlexander Motin if (quick) {
1639cf4fe2eSAlexander Motin if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
1649cf4fe2eSAlexander Motin return (0);
1655c2a4ae2SAlexander Motin if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE) {
1665c2a4ae2SAlexander Motin ata_sata_scr_write(ch, port, ATA_SCONTROL,
1675c2a4ae2SAlexander Motin ATA_SC_DET_IDLE | ((ch->pm_level > 0) ? 0 :
1685c2a4ae2SAlexander Motin ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER));
169bda55b6aSAlexander Motin return ata_sata_connect(ch, port, quick);
1709cf4fe2eSAlexander Motin }
1715c2a4ae2SAlexander Motin }
17213014ca0SSøren Schmidt
1739cf4fe2eSAlexander Motin if (bootverbose) {
1749cf4fe2eSAlexander Motin if (port < 0) {
1750eac2d6bSAlexander Motin device_printf(dev, "hard reset ...\n");
1769cf4fe2eSAlexander Motin } else {
1770eac2d6bSAlexander Motin device_printf(dev, "p%d: hard reset ...\n", port);
1789cf4fe2eSAlexander Motin }
1799cf4fe2eSAlexander Motin }
1809c87d811SAlexander Motin if (sata_rev == 1)
1819c87d811SAlexander Motin val1 = ATA_SC_SPD_SPEED_GEN1;
1829c87d811SAlexander Motin else if (sata_rev == 2)
1839c87d811SAlexander Motin val1 = ATA_SC_SPD_SPEED_GEN2;
1849c87d811SAlexander Motin else if (sata_rev == 3)
1859c87d811SAlexander Motin val1 = ATA_SC_SPD_SPEED_GEN3;
1869c87d811SAlexander Motin else
1879c87d811SAlexander Motin val1 = 0;
18813014ca0SSøren Schmidt for (retry = 0; retry < 10; retry++) {
18913014ca0SSøren Schmidt for (loop = 0; loop < 10; loop++) {
1909c87d811SAlexander Motin if (ata_sata_scr_write(ch, port, ATA_SCONTROL, ATA_SC_DET_RESET |
1919c87d811SAlexander Motin val1 | ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER))
1920eac2d6bSAlexander Motin goto fail;
19313014ca0SSøren Schmidt ata_udelay(100);
1949cf4fe2eSAlexander Motin if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
1950eac2d6bSAlexander Motin goto fail;
1969cf4fe2eSAlexander Motin if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_RESET)
19713014ca0SSøren Schmidt break;
19813014ca0SSøren Schmidt }
19913014ca0SSøren Schmidt ata_udelay(5000);
20013014ca0SSøren Schmidt for (loop = 0; loop < 10; loop++) {
2019cf4fe2eSAlexander Motin if (ata_sata_scr_write(ch, port, ATA_SCONTROL,
2029c87d811SAlexander Motin ATA_SC_DET_IDLE | val1 | ((ch->pm_level > 0) ? 0 :
2034c10f2e6SAlexander Motin ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)))
2040eac2d6bSAlexander Motin goto fail;
20513014ca0SSøren Schmidt ata_udelay(100);
2069cf4fe2eSAlexander Motin if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
2070eac2d6bSAlexander Motin goto fail;
2089cf4fe2eSAlexander Motin if ((val & ATA_SC_DET_MASK) == 0)
209bda55b6aSAlexander Motin return ata_sata_connect(ch, port, 0);
21013014ca0SSøren Schmidt }
21113014ca0SSøren Schmidt }
2120eac2d6bSAlexander Motin fail:
2130eac2d6bSAlexander Motin /* Clear SATA error register. */
2140eac2d6bSAlexander Motin ata_sata_scr_write(ch, port, ATA_SERROR, 0xffffffff);
2150eac2d6bSAlexander Motin
2160eac2d6bSAlexander Motin if (bootverbose) {
2170eac2d6bSAlexander Motin if (port < 0) {
2180eac2d6bSAlexander Motin device_printf(dev, "hard reset failed\n");
2190eac2d6bSAlexander Motin } else {
2200eac2d6bSAlexander Motin device_printf(dev, "p%d: hard reset failed\n", port);
2210eac2d6bSAlexander Motin }
2220eac2d6bSAlexander Motin }
2230eac2d6bSAlexander Motin return (0);
22413014ca0SSøren Schmidt }
22513014ca0SSøren Schmidt
226066f913aSAlexander Motin int
ata_sata_setmode(device_t dev,int target,int mode)227066f913aSAlexander Motin ata_sata_setmode(device_t dev, int target, int mode)
22813014ca0SSøren Schmidt {
22913014ca0SSøren Schmidt
230066f913aSAlexander Motin return (min(mode, ATA_UDMA5));
23113014ca0SSøren Schmidt }
232066f913aSAlexander Motin
233066f913aSAlexander Motin int
ata_sata_getrev(device_t dev,int target)234066f913aSAlexander Motin ata_sata_getrev(device_t dev, int target)
235066f913aSAlexander Motin {
236066f913aSAlexander Motin struct ata_channel *ch = device_get_softc(dev);
237066f913aSAlexander Motin
238066f913aSAlexander Motin if (ch->r_io[ATA_SSTATUS].res)
239066f913aSAlexander Motin return ((ATA_IDX_INL(ch, ATA_SSTATUS) & 0x0f0) >> 4);
2406a5d28b9SAlexander Motin return (0xff);
24113014ca0SSøren Schmidt }
24213014ca0SSøren Schmidt
24313014ca0SSøren Schmidt int
ata_request2fis_h2d(struct ata_request * request,u_int8_t * fis)24413014ca0SSøren Schmidt ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis)
24513014ca0SSøren Schmidt {
24613014ca0SSøren Schmidt
24713014ca0SSøren Schmidt if (request->flags & ATA_R_ATAPI) {
24813014ca0SSøren Schmidt fis[0] = 0x27; /* host to device */
249ebbb35baSAlexander Motin fis[1] = 0x80 | (request->unit & 0x0f);
25013014ca0SSøren Schmidt fis[2] = ATA_PACKET_CMD;
25113014ca0SSøren Schmidt if (request->flags & (ATA_R_READ | ATA_R_WRITE))
25213014ca0SSøren Schmidt fis[3] = ATA_F_DMA;
25313014ca0SSøren Schmidt else {
25413014ca0SSøren Schmidt fis[5] = request->transfersize;
25513014ca0SSøren Schmidt fis[6] = request->transfersize >> 8;
25613014ca0SSøren Schmidt }
25713014ca0SSøren Schmidt fis[7] = ATA_D_LBA;
25813014ca0SSøren Schmidt fis[15] = ATA_A_4BIT;
25913014ca0SSøren Schmidt return 20;
26013014ca0SSøren Schmidt }
26113014ca0SSøren Schmidt else {
26213014ca0SSøren Schmidt fis[0] = 0x27; /* host to device */
263ebbb35baSAlexander Motin fis[1] = 0x80 | (request->unit & 0x0f);
26413014ca0SSøren Schmidt fis[2] = request->u.ata.command;
26513014ca0SSøren Schmidt fis[3] = request->u.ata.feature;
26613014ca0SSøren Schmidt fis[4] = request->u.ata.lba;
26713014ca0SSøren Schmidt fis[5] = request->u.ata.lba >> 8;
26813014ca0SSøren Schmidt fis[6] = request->u.ata.lba >> 16;
26913014ca0SSøren Schmidt fis[7] = ATA_D_LBA;
270ebbb35baSAlexander Motin if (!(request->flags & ATA_R_48BIT))
27113014ca0SSøren Schmidt fis[7] |= (ATA_D_IBM | (request->u.ata.lba >> 24 & 0x0f));
27213014ca0SSøren Schmidt fis[8] = request->u.ata.lba >> 24;
27313014ca0SSøren Schmidt fis[9] = request->u.ata.lba >> 32;
27413014ca0SSøren Schmidt fis[10] = request->u.ata.lba >> 40;
27513014ca0SSøren Schmidt fis[11] = request->u.ata.feature >> 8;
27613014ca0SSøren Schmidt fis[12] = request->u.ata.count;
27713014ca0SSøren Schmidt fis[13] = request->u.ata.count >> 8;
27813014ca0SSøren Schmidt fis[15] = ATA_A_4BIT;
27913014ca0SSøren Schmidt return 20;
28013014ca0SSøren Schmidt }
28113014ca0SSøren Schmidt return 0;
28213014ca0SSøren Schmidt }
28313014ca0SSøren Schmidt
28413014ca0SSøren Schmidt void
ata_pm_identify(device_t dev)28513014ca0SSøren Schmidt ata_pm_identify(device_t dev)
28613014ca0SSøren Schmidt {
28713014ca0SSøren Schmidt struct ata_channel *ch = device_get_softc(dev);
28813014ca0SSøren Schmidt u_int32_t pm_chipid, pm_revision, pm_ports;
28913014ca0SSøren Schmidt int port;
29013014ca0SSøren Schmidt
29113014ca0SSøren Schmidt /* get PM vendor & product data */
29213014ca0SSøren Schmidt if (ch->hw.pm_read(dev, ATA_PM, 0, &pm_chipid)) {
29313014ca0SSøren Schmidt device_printf(dev, "error getting PM vendor data\n");
29413014ca0SSøren Schmidt return;
29513014ca0SSøren Schmidt }
29613014ca0SSøren Schmidt
29713014ca0SSøren Schmidt /* get PM revision data */
29813014ca0SSøren Schmidt if (ch->hw.pm_read(dev, ATA_PM, 1, &pm_revision)) {
299453130d9SPedro F. Giffuni device_printf(dev, "error getting PM revision data\n");
30013014ca0SSøren Schmidt return;
30113014ca0SSøren Schmidt }
30213014ca0SSøren Schmidt
30313014ca0SSøren Schmidt /* get number of HW ports on the PM */
30413014ca0SSøren Schmidt if (ch->hw.pm_read(dev, ATA_PM, 2, &pm_ports)) {
30513014ca0SSøren Schmidt device_printf(dev, "error getting PM port info\n");
30613014ca0SSøren Schmidt return;
30713014ca0SSøren Schmidt }
30813014ca0SSøren Schmidt pm_ports &= 0x0000000f;
30913014ca0SSøren Schmidt
31013014ca0SSøren Schmidt /* chip specific quirks */
31113014ca0SSøren Schmidt switch (pm_chipid) {
31213014ca0SSøren Schmidt case 0x37261095:
3139cf4fe2eSAlexander Motin /* This PM declares 6 ports, while only 5 of them are real.
3149cf4fe2eSAlexander Motin * Port 5 is enclosure management bridge port, which has implementation
3159cf4fe2eSAlexander Motin * problems, causing probe faults. Hide it for now. */
3169cf4fe2eSAlexander Motin device_printf(dev, "SiI 3726 (rev=%x) Port Multiplier with %d (5) ports\n",
31713014ca0SSøren Schmidt pm_revision, pm_ports);
3189cf4fe2eSAlexander Motin pm_ports = 5;
3199cf4fe2eSAlexander Motin break;
3209cf4fe2eSAlexander Motin
3219cf4fe2eSAlexander Motin case 0x47261095:
3229cf4fe2eSAlexander Motin /* This PM declares 7 ports, while only 5 of them are real.
3239cf4fe2eSAlexander Motin * Port 5 is some fake "Config Disk" with 640 sectors size,
3249cf4fe2eSAlexander Motin * port 6 is enclosure management bridge port.
3259cf4fe2eSAlexander Motin * Both fake ports has implementation problems, causing
3269cf4fe2eSAlexander Motin * probe faults. Hide them for now. */
3279cf4fe2eSAlexander Motin device_printf(dev, "SiI 4726 (rev=%x) Port Multiplier with %d (5) ports\n",
3289cf4fe2eSAlexander Motin pm_revision, pm_ports);
3299cf4fe2eSAlexander Motin pm_ports = 5;
33013014ca0SSøren Schmidt break;
33113014ca0SSøren Schmidt
33213014ca0SSøren Schmidt default:
3339cf4fe2eSAlexander Motin device_printf(dev, "Port Multiplier (id=%08x rev=%x) with %d ports\n",
33413014ca0SSøren Schmidt pm_chipid, pm_revision, pm_ports);
33513014ca0SSøren Schmidt }
33613014ca0SSøren Schmidt
33713014ca0SSøren Schmidt /* reset all ports and register if anything connected */
33813014ca0SSøren Schmidt for (port=0; port < pm_ports; port++) {
3399cf4fe2eSAlexander Motin u_int32_t signature;
34013014ca0SSøren Schmidt
3419cf4fe2eSAlexander Motin if (!ata_sata_phy_reset(dev, port, 1))
34213014ca0SSøren Schmidt continue;
34313014ca0SSøren Schmidt
3449cf4fe2eSAlexander Motin /*
3459cf4fe2eSAlexander Motin * XXX: I have no idea how to properly wait for PMP port hardreset
3469cf4fe2eSAlexander Motin * completion. Without this delay soft reset does not completes
3479cf4fe2eSAlexander Motin * successfully.
3489cf4fe2eSAlexander Motin */
3499cf4fe2eSAlexander Motin DELAY(1000000);
35013014ca0SSøren Schmidt
35113014ca0SSøren Schmidt signature = ch->hw.softreset(dev, port);
35213014ca0SSøren Schmidt
35313014ca0SSøren Schmidt if (bootverbose)
35413014ca0SSøren Schmidt device_printf(dev, "p%d: SIGNATURE=%08x\n", port, signature);
35513014ca0SSøren Schmidt
35613014ca0SSøren Schmidt /* figure out whats there */
357e412a8c3SAlexander Motin switch (signature >> 16) {
358e412a8c3SAlexander Motin case 0x0000:
35913014ca0SSøren Schmidt ch->devices |= (ATA_ATA_MASTER << port);
36013014ca0SSøren Schmidt continue;
361e412a8c3SAlexander Motin case 0xeb14:
36213014ca0SSøren Schmidt ch->devices |= (ATA_ATAPI_MASTER << port);
36313014ca0SSøren Schmidt continue;
36413014ca0SSøren Schmidt }
36513014ca0SSøren Schmidt }
36613014ca0SSøren Schmidt }
367