LCOV - code coverage report
Current view: top level - dev/ic - sili.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 805 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 47 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: sili.c,v 1.58 2015/12/19 20:05:32 tb Exp $ */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
       5             :  * Copyright (c) 2010 Conformal Systems LLC <info@conformal.com>
       6             :  * Copyright (c) 2010 Jonathan Matthew <jonathan@d14n.org>
       7             :  *
       8             :  * Permission to use, copy, modify, and distribute this software for any
       9             :  * purpose with or without fee is hereby granted, provided that the above
      10             :  * copyright notice and this permission notice appear in all copies.
      11             :  *
      12             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      13             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      14             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      15             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      16             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      17             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      18             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      19             :  */
      20             : 
      21             : #include <sys/param.h>
      22             : #include <sys/systm.h>
      23             : #include <sys/device.h>
      24             : #include <sys/timeout.h>
      25             : #include <sys/malloc.h>
      26             : #include <sys/kernel.h>
      27             : #include <sys/mutex.h>
      28             : 
      29             : #include <machine/bus.h>
      30             : 
      31             : #include <dev/ata/atascsi.h>
      32             : #include <dev/ata/pmreg.h>
      33             : 
      34             : #include <dev/ic/silireg.h>
      35             : #include <dev/ic/silivar.h>
      36             : 
      37             : /* use SILI_DEBUG for dmesg spam */
      38             : #define NO_SILI_DEBUG
      39             : 
      40             : #ifdef SILI_DEBUG
      41             : #define SILI_D_VERBOSE          (1<<0)
      42             : #define SILI_D_INTR             (1<<1)
      43             : 
      44             : int silidebug = SILI_D_VERBOSE;
      45             : 
      46             : #define DPRINTF(m, a...)        do { if ((m) & silidebug) printf(a); } while (0)
      47             : #else
      48             : #define DPRINTF(m, a...)
      49             : #endif
      50             : 
      51             : /* these can be used to simulate read and write errors on specific PMP ports */
      52             : #undef SILI_ERROR_TEST
      53             : int sili_error_pmp_ports = 0;           /* bitmask containing ports to fail*/
      54             : int sili_error_test_inv_p = 500;        /* 1/P(error) */
      55             : int sili_error_restart_type = SILI_PREG_PCS_PORTINIT; /* or _DEVRESET */
      56             : 
      57             : struct cfdriver sili_cd = {
      58             :         NULL, "sili", DV_DULL
      59             : };
      60             : 
      61             : /* wrapper around dma memory */
      62             : struct sili_dmamem {
      63             :         bus_dmamap_t            sdm_map;
      64             :         bus_dma_segment_t       sdm_seg;
      65             :         size_t                  sdm_size;
      66             :         caddr_t                 sdm_kva;
      67             : };
      68             : #define SILI_DMA_MAP(_sdm)      ((_sdm)->sdm_map)
      69             : #define SILI_DMA_DVA(_sdm)      ((_sdm)->sdm_map->dm_segs[0].ds_addr)
      70             : #define SILI_DMA_KVA(_sdm)      ((_sdm)->sdm_kva)
      71             : 
      72             : struct sili_dmamem      *sili_dmamem_alloc(struct sili_softc *, bus_size_t,
      73             :                             bus_size_t);
      74             : void                    sili_dmamem_free(struct sili_softc *,
      75             :                             struct sili_dmamem *);
      76             : 
      77             : /* per port goo */
      78             : struct sili_ccb;
      79             : 
      80             : /* size of scratch space for use in error recovery. */
      81             : #define SILI_SCRATCH_LEN        512     /* must be at least 1 sector */
      82             : 
      83             : struct sili_port {
      84             :         struct sili_softc       *sp_sc;
      85             :         bus_space_handle_t      sp_ioh;
      86             : 
      87             :         struct sili_ccb         *sp_ccbs;
      88             :         struct sili_dmamem      *sp_cmds;
      89             :         struct sili_dmamem      *sp_scratch;
      90             : 
      91             :         TAILQ_HEAD(, sili_ccb)  sp_free_ccbs;
      92             :         struct mutex            sp_free_ccb_mtx;
      93             : 
      94             :         volatile u_int32_t      sp_active;
      95             :         TAILQ_HEAD(, sili_ccb)  sp_active_ccbs;
      96             :         TAILQ_HEAD(, sili_ccb)  sp_deferred_ccbs;
      97             : 
      98             :         int                     sp_port;
      99             :         int                     sp_pmp_ports;
     100             :         int                     sp_active_pmp_ports;
     101             :         int                     sp_pmp_error_recovery;  /* port bitmask */
     102             :         volatile u_int32_t      sp_err_active;          /* cmd bitmask */
     103             :         volatile u_int32_t      sp_err_cmds;            /* cmd bitmask */
     104             : 
     105             : #ifdef SILI_DEBUG
     106             :         char                    sp_name[16];
     107             : #define PORTNAME(_sp)   ((_sp)->sp_name)
     108             : #else
     109             : #define PORTNAME(_sp)   DEVNAME((_sp)->sp_sc)
     110             : #endif
     111             : };
     112             : 
     113             : int                     sili_ports_alloc(struct sili_softc *);
     114             : void                    sili_ports_free(struct sili_softc *);
     115             : 
     116             : /* ccb shizz */
     117             : 
     118             : /*
     119             :  * the dma memory for each command will be made up of a prb followed by
     120             :  * 7 sgts, this is a neat 512 bytes.
     121             :  */
     122             : #define SILI_CMD_LEN            512
     123             : 
     124             : /*
     125             :  * you can fit 22 sge's into 7 sgts and a prb:
     126             :  * there's 1 sgl in an atapi prb (two in the ata one, but we cant over
     127             :  * advertise), but that's needed for the chain element. you get three sges
     128             :  * per sgt cos you lose the 4th sge for the chaining, but you keep it in
     129             :  * the last sgt. so 3 x 6 + 4 is 22.
     130             :  */
     131             : #define SILI_DMA_SEGS           22
     132             : 
     133             : struct sili_ccb {
     134             :         struct ata_xfer         ccb_xa;
     135             : 
     136             :         void                    *ccb_cmd;
     137             :         u_int64_t               ccb_cmd_dva;
     138             :         bus_dmamap_t            ccb_dmamap;
     139             : 
     140             :         struct sili_port        *ccb_port;
     141             : 
     142             :         TAILQ_ENTRY(sili_ccb)   ccb_entry;
     143             : };
     144             : 
     145             : int                     sili_ccb_alloc(struct sili_port *);
     146             : void                    sili_ccb_free(struct sili_port *);
     147             : struct sili_ccb         *sili_get_ccb(struct sili_port *);
     148             : void                    sili_put_ccb(struct sili_ccb *);
     149             : 
     150             : /* bus space ops */
     151             : u_int32_t               sili_read(struct sili_softc *, bus_size_t);
     152             : void                    sili_write(struct sili_softc *, bus_size_t, u_int32_t);
     153             : u_int32_t               sili_pread(struct sili_port *, bus_size_t);
     154             : void                    sili_pwrite(struct sili_port *, bus_size_t, u_int32_t);
     155             : int                     sili_pwait_eq(struct sili_port *, bus_size_t,
     156             :                             u_int32_t, u_int32_t, int);
     157             : int                     sili_pwait_ne(struct sili_port *, bus_size_t,
     158             :                             u_int32_t, u_int32_t, int);
     159             : 
     160             : /* command handling */
     161             : void                    sili_post_direct(struct sili_port *, u_int,
     162             :                             void *, size_t buflen);
     163             : void                    sili_post_indirect(struct sili_port *,
     164             :                             struct sili_ccb *);
     165             : void                    sili_pread_fis(struct sili_port *, u_int,
     166             :                             struct ata_fis_d2h *);
     167             : u_int32_t               sili_signature(struct sili_port *, u_int);
     168             : u_int32_t               sili_port_softreset(struct sili_port *sp);
     169             : int                     sili_load(struct sili_ccb *, struct sili_sge *, int);
     170             : void                    sili_unload(struct sili_ccb *);
     171             : int                     sili_poll(struct sili_ccb *, int, void (*)(void *));
     172             : void                    sili_start(struct sili_port *, struct sili_ccb *);
     173             : int                     sili_read_ncq_error(struct sili_port *, int *, int);
     174             : int                     sili_pmp_port_start_error_recovery(struct sili_port *,
     175             :                             int);
     176             : void                    sili_pmp_port_do_error_recovery(struct sili_port *,
     177             :                             int, u_int32_t *);
     178             : void                    sili_port_clear_commands(struct sili_port *sp);
     179             : 
     180             : /* pmp operations */
     181             : int                     sili_pmp_read(struct sili_port *, int, int,
     182             :                             u_int32_t *);
     183             : int                     sili_pmp_write(struct sili_port *, int, int, u_int32_t);
     184             : int                     sili_pmp_phy_status(struct sili_port *, int,
     185             :                             u_int32_t *);
     186             : int                     sili_pmp_identify(struct sili_port *, int *);
     187             : 
     188             : /* port interrupt handler */
     189             : u_int32_t               sili_port_intr(struct sili_port *, int);
     190             : 
     191             : /* atascsi interface */
     192             : int                     sili_ata_probe(void *, int, int);
     193             : void                    sili_ata_free(void *, int, int);
     194             : struct ata_xfer         *sili_ata_get_xfer(void *, int);
     195             : void                    sili_ata_put_xfer(struct ata_xfer *);
     196             : void                    sili_ata_cmd(struct ata_xfer *);
     197             : int                     sili_pmp_portreset(struct sili_softc *, int, int);
     198             : int                     sili_pmp_softreset(struct sili_softc *, int, int);
     199             : 
     200             : #ifdef SILI_ERROR_TEST
     201             : void                    sili_simulate_error(struct sili_ccb *ccb,
     202             :                             int *need_restart, int *err_port);
     203             : #endif
     204             : 
     205             : struct atascsi_methods sili_atascsi_methods = {
     206             :         sili_ata_probe,
     207             :         sili_ata_free,
     208             :         sili_ata_get_xfer,
     209             :         sili_ata_put_xfer,
     210             :         sili_ata_cmd
     211             : };
     212             : 
     213             : /* completion paths */
     214             : void                    sili_ata_cmd_done(struct sili_ccb *, int);
     215             : void                    sili_ata_cmd_timeout(void *);
     216             : void                    sili_dummy_done(struct ata_xfer *);
     217             : 
     218             : void                    sili_pmp_op_timeout(void *);
     219             : 
     220             : int
     221           0 : sili_attach(struct sili_softc *sc)
     222             : {
     223           0 :         struct atascsi_attach_args      aaa;
     224             : 
     225           0 :         printf("\n");
     226             : 
     227           0 :         if (sili_ports_alloc(sc) != 0) {
     228             :                 /* error already printed by sili_port_alloc */
     229           0 :                 return (1);
     230             :         }
     231             : 
     232             :         /* bounce the controller */
     233           0 :         sili_write(sc, SILI_REG_GC, SILI_REG_GC_GR);
     234           0 :         sili_write(sc, SILI_REG_GC, 0x0);
     235             : 
     236           0 :         bzero(&aaa, sizeof(aaa));
     237           0 :         aaa.aaa_cookie = sc;
     238           0 :         aaa.aaa_methods = &sili_atascsi_methods;
     239           0 :         aaa.aaa_minphys = NULL;
     240           0 :         aaa.aaa_nports = sc->sc_nports;
     241           0 :         aaa.aaa_ncmds = SILI_MAX_CMDS;
     242           0 :         aaa.aaa_capability = ASAA_CAP_NCQ | ASAA_CAP_PMP_NCQ;
     243             : 
     244           0 :         sc->sc_atascsi = atascsi_attach(&sc->sc_dev, &aaa);
     245             : 
     246           0 :         return (0);
     247           0 : }
     248             : 
     249             : int
     250           0 : sili_detach(struct sili_softc *sc, int flags)
     251             : {
     252             :         int                             rv;
     253             : 
     254           0 :         if (sc->sc_atascsi != NULL) {
     255           0 :                 rv = atascsi_detach(sc->sc_atascsi, flags);
     256           0 :                 if (rv != 0)
     257           0 :                         return (rv);
     258             :         }
     259             : 
     260           0 :         if (sc->sc_ports != NULL)
     261           0 :                 sili_ports_free(sc);
     262             : 
     263           0 :         return (0);
     264           0 : }
     265             : 
     266             : void
     267           0 : sili_resume(struct sili_softc *sc)
     268             : {
     269             :         int i, j;
     270             : 
     271             :         /* bounce the controller */
     272           0 :         sili_write(sc, SILI_REG_GC, SILI_REG_GC_GR);
     273           0 :         sili_write(sc, SILI_REG_GC, 0x0);
     274             : 
     275           0 :         for (i = 0; i < sc->sc_nports; i++) {
     276           0 :                 if (sili_ata_probe(sc, i, 0) == ATA_PORT_T_PM) {
     277           0 :                         struct sili_port *sp = &sc->sc_ports[i];
     278           0 :                         for (j = 0; j < sp->sp_pmp_ports; j++) {
     279           0 :                                 sili_ata_probe(sc, i, j);
     280             :                         }
     281           0 :                 }
     282             :         }
     283           0 : }
     284             : 
     285             : int
     286           0 : sili_pmp_port_start_error_recovery(struct sili_port *sp, int err_port)
     287             : {
     288             :         struct sili_ccb *ccb;
     289             : 
     290           0 :         sp->sp_pmp_error_recovery |= (1 << err_port);
     291             : 
     292             :         /* create a bitmask of active commands on non-error ports */
     293           0 :         sp->sp_err_active = 0;
     294           0 :         TAILQ_FOREACH(ccb, &sp->sp_active_ccbs, ccb_entry) {
     295           0 :                 int bit = (1 << ccb->ccb_xa.pmp_port);
     296           0 :                 if ((sp->sp_pmp_error_recovery & bit) == 0) {
     297             :                         DPRINTF(SILI_D_VERBOSE, "%s: slot %d active on port "
     298             :                             "%d\n", PORTNAME(sp), ccb->ccb_xa.tag,
     299             :                             ccb->ccb_xa.pmp_port);
     300           0 :                         sp->sp_err_active |= (1 << ccb->ccb_xa.tag);
     301           0 :                 }
     302             :         }
     303             : 
     304           0 :         if (sp->sp_err_active == 0) {
     305             :                 DPRINTF(SILI_D_VERBOSE, "%s: no other PMP ports active\n",
     306             :                     PORTNAME(sp));
     307           0 :                 sp->sp_pmp_error_recovery = 0;
     308           0 :                 return (0);
     309             :         }
     310             : 
     311             :         /* set port resume */
     312           0 :         sili_pwrite(sp, SILI_PREG_PCS, SILI_PREG_PCS_RESUME);
     313             : 
     314             :         DPRINTF(SILI_D_VERBOSE, "%s: beginning error recovery (port %d); "
     315             :             "error port mask %x, active slot mask %x\n", PORTNAME(sp), err_port,
     316             :             sp->sp_pmp_error_recovery, sp->sp_err_active);
     317           0 :         return (1);
     318           0 : }
     319             : 
     320             : void
     321           0 : sili_port_clear_commands(struct sili_port *sp)
     322             : {
     323             :         int port;
     324             : 
     325             :         DPRINTF(SILI_D_VERBOSE, "%s: clearing active commands\n",
     326             :             PORTNAME(sp));
     327             : 
     328             :         /* clear port resume */
     329           0 :         sili_pwrite(sp, SILI_PREG_PCC, SILI_PREG_PCC_RESUME);
     330           0 :         delay(10000);
     331             : 
     332             :         /* clear port status and port active for all ports */
     333           0 :         for (port = 0; port < 16; port++) {
     334           0 :                 sili_pwrite(sp, SILI_PREG_PMP_STATUS(port), 0);
     335           0 :                 sili_pwrite(sp, SILI_PREG_PMP_QACTIVE(port), 0);
     336             :         }
     337           0 : }
     338             : 
     339             : void
     340           0 : sili_pmp_port_do_error_recovery(struct sili_port *sp, int slot,
     341             :     u_int32_t *need_restart)
     342             : {
     343           0 :         if (sp->sp_pmp_error_recovery == 0) {
     344             :                 return;
     345             :         }
     346             : 
     347             :         /* have all outstanding commands finished yet? */
     348           0 :         if (sp->sp_err_active != 0) {
     349             :                 DPRINTF(SILI_D_VERBOSE, "%s: PMP error recovery still waiting "
     350             :                     "for %x\n", PORTNAME(sp), sp->sp_err_active);
     351           0 :                 *need_restart = 0;
     352           0 :                 return;
     353             :         }
     354             : 
     355           0 :         sili_port_clear_commands(sp);
     356             : 
     357             :         /* get the main error recovery code to reset the port and
     358             :          * resubmit commands.  it will also reset the error recovery flags.
     359             :          */
     360           0 :         *need_restart = SILI_PREG_PCS_PORTINIT;
     361             :         DPRINTF(SILI_D_VERBOSE, "%s: PMP error recovery complete\n",
     362             :             PORTNAME(sp));
     363           0 : }
     364             : 
     365             : #ifdef SILI_ERROR_TEST
     366             : void
     367             : sili_simulate_error(struct sili_ccb *ccb, int *need_restart, int *err_port)
     368             : {
     369             :         struct sili_port *sp = ccb->ccb_port;
     370             : 
     371             :         if (*need_restart == 0 &&
     372             :             ((1 << ccb->ccb_xa.pmp_port) & sili_error_pmp_ports)) {
     373             :                 switch (ccb->ccb_xa.fis->command) {
     374             :                 case ATA_C_WRITE_FPDMA:
     375             :                 case ATA_C_READ_FPDMA:
     376             :                 case ATA_C_WRITEDMA_EXT:
     377             :                 case ATA_C_READDMA_EXT:
     378             :                 case ATA_C_WRITEDMA:
     379             :                 case ATA_C_READDMA:
     380             :                         if (arc4random_uniform(sili_error_test_inv_p) == 0) {
     381             :                                 printf("%s: faking error on slot %d\n",
     382             :                                     PORTNAME(sp), ccb->ccb_xa.tag);
     383             :                                 ccb->ccb_xa.state = ATA_S_ERROR;
     384             :                                 *need_restart = sili_error_restart_type;
     385             :                                 *err_port = ccb->ccb_xa.pmp_port;
     386             : 
     387             :                                 ccb->ccb_port->sp_err_cmds |=
     388             :                                     (1 << ccb->ccb_xa.tag);
     389             :                         }
     390             :                         break;
     391             : 
     392             :                 default:
     393             :                         /* leave other commands alone, we only want to mess
     394             :                          * with normal read/write ops
     395             :                          */
     396             :                         break;
     397             :                 }
     398             :         }
     399             : }
     400             : #endif
     401             : 
     402             : u_int32_t
     403           0 : sili_port_intr(struct sili_port *sp, int timeout_slot)
     404             : {
     405             :         u_int32_t                       is, pss_saved, pss_masked;
     406           0 :         u_int32_t                       processed = 0, need_restart = 0;
     407             :         u_int32_t                       err_port = 0;
     408             :         int                             slot;
     409             :         struct sili_ccb                 *ccb;
     410             : 
     411           0 :         is = sili_pread(sp, SILI_PREG_IS);
     412           0 :         pss_saved = sili_pread(sp, SILI_PREG_PSS); /* reading acks CMDCOMP */
     413             : 
     414             : #ifdef SILI_DEBUG
     415             :         if ((pss_saved & SILI_PREG_PSS_ALL_SLOTS) != sp->sp_active ||
     416             :             ((is >> 16) & ~SILI_PREG_IS_CMDCOMP)) {
     417             :                 DPRINTF(SILI_D_INTR, "%s: IS: 0x%08x (0x%b), PSS: %08x, "
     418             :                     "active: %08x\n", PORTNAME(sp), is, is >> 16, SILI_PFMT_IS,
     419             :                     pss_saved, sp->sp_active);
     420             :         }
     421             : #endif
     422             : 
     423             :         /* Only interested in slot status bits. */
     424           0 :         pss_saved &= SILI_PREG_PSS_ALL_SLOTS;
     425             : 
     426           0 :         if (is & SILI_PREG_IS_CMDERR) {
     427           0 :                 int                     err_slot, err_code;
     428             :                 u_int32_t               sactive = 0;
     429             : 
     430           0 :                 sili_pwrite(sp, SILI_PREG_IS, SILI_PREG_IS_CMDERR);
     431           0 :                 err_slot = SILI_PREG_PCS_ACTIVE(sili_pread(sp, SILI_PREG_PCS));
     432           0 :                 err_code = sili_pread(sp, SILI_PREG_CE);
     433           0 :                 ccb = &sp->sp_ccbs[err_slot];
     434             : 
     435           0 :                 switch (err_code) {
     436             :                 case SILI_PREG_CE_DEVICEERROR:
     437             :                 case SILI_PREG_CE_DATAFISERROR:
     438             :                         /* Extract error from command slot in LRAM. */
     439           0 :                         sili_pread_fis(sp, err_slot, &ccb->ccb_xa.rfis);
     440           0 :                         err_port = ccb->ccb_xa.pmp_port;
     441           0 :                         break;
     442             : 
     443             :                 case SILI_PREG_CE_SDBERROR:
     444             : 
     445           0 :                         if (sp->sp_pmp_ports > 0) {
     446             :                                 /* get the PMP port number for the error */
     447           0 :                                 err_port = (sili_pread(sp, SILI_PREG_CONTEXT)
     448           0 :                                     >> SILI_PREG_CONTEXT_PMPORT_SHIFT) &
     449             :                                     SILI_PREG_CONTEXT_PMPORT_MASK;
     450             :                                 DPRINTF(SILI_D_VERBOSE, "%s: error port is "
     451             :                                     "%d\n", PORTNAME(sp), err_port);
     452             : 
     453             :                                 /* were there any NCQ commands active for
     454             :                                  * the port?
     455             :                                  */
     456           0 :                                 sactive = sili_pread(sp,
     457           0 :                                     SILI_PREG_PMP_QACTIVE(err_port));
     458             :                                 DPRINTF(SILI_D_VERBOSE, "%s: error SActive "
     459             :                                     "%x\n", PORTNAME(sp), sactive);
     460           0 :                                 if (sactive == 0)
     461             :                                         break;
     462             :                         } else {
     463             :                                 /* No NCQ commands active?  Treat as a normal
     464             :                                  * error.
     465             :                                  */
     466           0 :                                 sactive = sili_pread(sp, SILI_PREG_SACT);
     467           0 :                                 if (sactive == 0)
     468             :                                         break;
     469             :                         }
     470             : 
     471             :                         /* Extract real NCQ error slot & RFIS from
     472             :                          * log page.
     473             :                          */ 
     474           0 :                         if (!sili_read_ncq_error(sp, &err_slot, err_port)) {
     475             :                                 /* got real err_slot */
     476             :                                 DPRINTF(SILI_D_VERBOSE, "%s.%d: error slot "
     477             :                                     "%d\n", PORTNAME(sp), err_port, err_slot);
     478           0 :                                 ccb = &sp->sp_ccbs[err_slot];
     479           0 :                                 break;
     480             :                         }
     481             :                         DPRINTF(SILI_D_VERBOSE, "%s.%d: failed to get error "
     482             :                             "slot\n", PORTNAME(sp), err_port);
     483             : 
     484             :                         /* failed to get error or not NCQ */
     485             : 
     486             :                         /* FALLTHROUGH */
     487             :                 default:
     488             :                         /* All other error types are fatal. */
     489           0 :                         if (err_code != SILI_PREG_CE_SDBERROR) {
     490           0 :                                 err_port = (sili_pread(sp, SILI_PREG_CONTEXT)
     491           0 :                                     >> SILI_PREG_CONTEXT_PMPORT_SHIFT) &
     492             :                                     SILI_PREG_CONTEXT_PMPORT_MASK;
     493           0 :                         }
     494           0 :                         printf("%s.%d: fatal error (%d), aborting active slots "
     495           0 :                             "(%08x) and resetting device.\n", PORTNAME(sp),
     496             :                             err_port, err_code, pss_saved);
     497           0 :                         while (pss_saved) {
     498           0 :                                 slot = ffs(pss_saved) - 1;
     499           0 :                                 pss_saved &= ~(1 << slot);
     500             : 
     501           0 :                                 ccb = &sp->sp_ccbs[slot];
     502           0 :                                 KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
     503           0 :                                 ccb->ccb_xa.state = ATA_S_ERROR;
     504             :                         }
     505           0 :                         need_restart = SILI_PREG_PCS_DEVRESET;
     506           0 :                         goto fatal;
     507             :                 }
     508             : 
     509             :                 DPRINTF(SILI_D_VERBOSE, "%s.%d: %serror, code %d, slot %d, "
     510             :                     "active %08x\n", PORTNAME(sp), err_port,
     511             :                     sactive ? "NCQ " : "", err_code, err_slot, sp->sp_active);
     512             : 
     513             :                 /* Clear the failed commmand in saved PSS so cmd_done runs. */
     514           0 :                 pss_saved &= ~(1 << err_slot);
     515             :                 /* Track errored commands until we finish recovery */
     516           0 :                 sp->sp_err_cmds |= (1 << err_slot);
     517             : 
     518           0 :                 KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
     519           0 :                 ccb->ccb_xa.state = ATA_S_ERROR;
     520             : 
     521           0 :                 need_restart = SILI_PREG_PCS_PORTINIT;
     522           0 :         }
     523             : fatal:
     524             : 
     525             :         /* Process command timeout request only if command is still active. */
     526           0 :         if (timeout_slot >= 0 && (pss_saved & (1 << timeout_slot))) {
     527             :                 DPRINTF(SILI_D_VERBOSE, "%s: timing out slot %d, active %08x\n",
     528             :                     PORTNAME(sp), timeout_slot, sp->sp_active);
     529             : 
     530             :                 /* Clear the failed commmand in saved PSS so cmd_done runs. */
     531           0 :                 pss_saved &= ~(1 << timeout_slot);
     532             : 
     533           0 :                 ccb = &sp->sp_ccbs[timeout_slot];
     534           0 :                 KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
     535           0 :                 ccb->ccb_xa.state = ATA_S_TIMEOUT;
     536             : 
     537             :                 /* Reinitialise the port and clear all active commands */
     538           0 :                 need_restart = SILI_PREG_PCS_PORTINIT;
     539             : 
     540           0 :                 err_port = ccb->ccb_xa.pmp_port;
     541           0 :                 sp->sp_err_cmds |= (1 << timeout_slot);
     542             : 
     543           0 :                 sili_port_clear_commands(sp);
     544           0 :         }
     545             : 
     546             :         /* Command slot is complete if its bit in PSS is 0 but 1 in active. */
     547           0 :         pss_masked = ~pss_saved & sp->sp_active;
     548           0 :         while (pss_masked) {
     549           0 :                 slot = ffs(pss_masked) - 1;
     550           0 :                 ccb = &sp->sp_ccbs[slot];
     551           0 :                 pss_masked &= ~(1 << slot);
     552             : 
     553             :                 /* copy the rfis into the ccb if we were asked for it */
     554           0 :                 if (ccb->ccb_xa.state == ATA_S_ONCHIP &&
     555           0 :                     ccb->ccb_xa.flags & ATA_F_GET_RFIS) {
     556           0 :                         sili_pread_fis(sp, slot, &ccb->ccb_xa.rfis);
     557           0 :                 }
     558             : 
     559             : #ifdef SILI_ERROR_TEST
     560             :                 /* introduce random errors on reads and writes for testing */
     561             :                 sili_simulate_error(ccb, &need_restart, &err_port);
     562             : #endif
     563             : 
     564             :                 DPRINTF(SILI_D_INTR, "%s: slot %d is complete%s%s\n",
     565             :                     PORTNAME(sp), slot, ccb->ccb_xa.state == ATA_S_ERROR ?
     566             :                     " (error)" : (ccb->ccb_xa.state == ATA_S_TIMEOUT ?
     567             :                     " (timeout)" : ""),
     568             :                     ccb->ccb_xa.flags & ATA_F_NCQ ? " (ncq)" : "");
     569             : 
     570           0 :                 sili_ata_cmd_done(ccb, need_restart);
     571             : 
     572           0 :                 processed |= 1 << slot;
     573             : 
     574           0 :                 sili_pmp_port_do_error_recovery(sp, slot, &need_restart);
     575             :         }
     576             : 
     577           0 :         if (need_restart) {
     578             : 
     579           0 :                 if (sp->sp_pmp_error_recovery) {
     580           0 :                         if (sp->sp_err_active != 0) {
     581             :                                 DPRINTF(SILI_D_VERBOSE, "%s: still waiting for "
     582             :                                     "non-error commands to finish; port mask "
     583             :                                     "%x, slot mask %x\n", PORTNAME(sp),
     584             :                                     sp->sp_pmp_error_recovery,
     585             :                                     sp->sp_err_active);
     586           0 :                                 return (processed);
     587             :                         }
     588           0 :                 } else if (timeout_slot < 0 && sp->sp_pmp_ports > 0) {
     589             :                         /* wait until all other commands have finished before
     590             :                          * attempting to reinit the port.
     591             :                          */
     592             :                         DPRINTF(SILI_D_VERBOSE, "%s: error on port with PMP "
     593             :                             "attached, error port %d\n", PORTNAME(sp),
     594             :                             err_port);
     595           0 :                         if (sili_pmp_port_start_error_recovery(sp, err_port)) {
     596             :                                 DPRINTF(SILI_D_VERBOSE, "%s: need to wait for "
     597             :                                     "other commands to finish\n", PORTNAME(sp));
     598           0 :                                 return (processed);
     599             :                         }
     600             :                 } else if (sp->sp_pmp_ports > 0) {
     601             :                         DPRINTF(SILI_D_VERBOSE, "%s: timeout on PMP port\n",
     602             :                             PORTNAME(sp));
     603             :                 } else {
     604             :                         DPRINTF(SILI_D_VERBOSE, "%s: error on non-PMP port\n",
     605             :                             PORTNAME(sp));
     606             :                 }
     607             : 
     608             :                 /* Re-enable transfers on port. */
     609           0 :                 sili_pwrite(sp, SILI_PREG_PCS, need_restart);
     610           0 :                 if (!sili_pwait_eq(sp, SILI_PREG_PCS, need_restart, 0, 5000)) {
     611           0 :                         printf("%s: port reset bit didn't clear after error\n",
     612           0 :                             PORTNAME(sp));
     613           0 :                 }
     614           0 :                 if (!sili_pwait_eq(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTRDY,
     615             :                     SILI_PREG_PCS_PORTRDY, 1000)) {
     616           0 :                         printf("%s: couldn't restart port after error\n",
     617           0 :                             PORTNAME(sp));
     618           0 :                 }
     619           0 :                 sili_pwrite(sp, SILI_PREG_PCC, SILI_PREG_PCC_RESUME);
     620             : 
     621             :                 /* check that our active CCB list matches the restart mask */
     622           0 :                 pss_masked = pss_saved & ~(sp->sp_err_cmds);
     623             :                 DPRINTF(SILI_D_VERBOSE, "%s: restart mask %x\n",
     624             :                     PORTNAME(sp), pss_masked);
     625           0 :                 TAILQ_FOREACH(ccb, &sp->sp_active_ccbs, ccb_entry) {
     626           0 :                         if (!(pss_masked & (1 << ccb->ccb_xa.tag))) {
     627           0 :                                 panic("sili_intr: slot %d not active in "
     628             :                                     "pss_masked: %08x, state %02x",
     629             :                                     ccb->ccb_xa.tag, pss_masked,
     630           0 :                                     ccb->ccb_xa.state);
     631             :                         }
     632           0 :                         pss_masked &= ~(1 << ccb->ccb_xa.tag);
     633             :                 }
     634           0 :                 if (pss_masked != 0) {
     635           0 :                         printf("%s: mask excluding active slots: %x\n",
     636           0 :                             PORTNAME(sp), pss_masked);
     637           0 :                 }
     638           0 :                 KASSERT(pss_masked == 0);
     639             :                 
     640             :                 /* if we had a timeout on a PMP port, do a portreset.
     641             :                  * exclude the control port here as there isn't a real
     642             :                  * device there to reset.
     643             :                  */
     644           0 :                 if (timeout_slot >= 0 && sp->sp_pmp_ports > 0 &&
     645           0 :                     err_port != 15) {
     646             : 
     647             :                         DPRINTF(SILI_D_VERBOSE,
     648             :                             "%s.%d: doing portreset after timeout\n",
     649             :                             PORTNAME(sp), err_port);
     650           0 :                         sili_pmp_portreset(sp->sp_sc, sp->sp_port, err_port);
     651             : 
     652             :                         /* wait a bit to let the port settle down */
     653           0 :                         delay(2000000);
     654           0 :                 }
     655             : 
     656             :                 /* if we sent a device reset to a PMP, we need to reset the
     657             :                  * devices behind it too.
     658             :                  */
     659           0 :                 if (need_restart == SILI_PREG_PCS_DEVRESET &&
     660           0 :                     sp->sp_pmp_ports > 0) {
     661             :                         int port_type;
     662             :                         int i;
     663             : 
     664           0 :                         port_type = sili_port_softreset(sp);
     665           0 :                         if (port_type != ATA_PORT_T_PM) {
     666             :                                 /* device disappeared or changed type? */
     667           0 :                                 printf("%s: expected to find a port multiplier,"
     668           0 :                                     " got %d\n", PORTNAME(sp), port_type);
     669           0 :                         }
     670             : 
     671             :                         /* and now portreset all active ports */
     672           0 :                         for (i = 0; i < sp->sp_pmp_ports; i++) {
     673           0 :                                 struct sili_softc *sc = sp->sp_sc;
     674             : 
     675           0 :                                 if ((sp->sp_active_pmp_ports & (1 << i)) == 0)
     676           0 :                                         continue;
     677             : 
     678           0 :                                 if (sili_pmp_portreset(sc, sp->sp_port, i)) {
     679           0 :                                         printf("%s.%d: failed to portreset "
     680           0 :                                             "after error\n", PORTNAME(sp), i);
     681           0 :                                 }
     682           0 :                         }
     683           0 :                 }
     684             : 
     685             :                 /* Restart CCBs in the order they were originally queued. */
     686           0 :                 TAILQ_FOREACH(ccb, &sp->sp_active_ccbs, ccb_entry) {
     687             :                         DPRINTF(SILI_D_VERBOSE, "%s: restarting slot %d "
     688             :                             "after error, state %02x\n", PORTNAME(sp),
     689             :                             ccb->ccb_xa.tag, ccb->ccb_xa.state);
     690           0 :                         KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
     691           0 :                         sili_post_indirect(sp, ccb);
     692             :                 }
     693           0 :                 sp->sp_err_cmds = 0;
     694           0 :                 sp->sp_pmp_error_recovery = 0;
     695             :                 
     696             :                 /*
     697             :                  * Finally, run atascsi completion for any finished CCBs.  If
     698             :                  * we had run these during cmd_done above, any ccbs that their
     699             :                  * completion generated would have been activated out of order.
     700             :                  */
     701           0 :                 while ((ccb = TAILQ_FIRST(&sp->sp_deferred_ccbs)) != NULL) {
     702           0 :                         TAILQ_REMOVE(&sp->sp_deferred_ccbs, ccb, ccb_entry);
     703             : 
     704             :                         DPRINTF(SILI_D_VERBOSE, "%s: running deferred "
     705             :                             "completion for slot %d, state %02x\n",
     706             :                             PORTNAME(sp), ccb->ccb_xa.tag, ccb->ccb_xa.state);
     707           0 :                         KASSERT(ccb->ccb_xa.state == ATA_S_COMPLETE ||
     708             :                             ccb->ccb_xa.state == ATA_S_ERROR ||
     709             :                             ccb->ccb_xa.state == ATA_S_TIMEOUT);
     710           0 :                         ata_complete(&ccb->ccb_xa);
     711             :                 }
     712             :         }
     713             : 
     714           0 :         return (processed);
     715           0 : }
     716             : 
     717             : int
     718           0 : sili_intr(void *arg)
     719             : {
     720           0 :         struct sili_softc               *sc = arg;
     721             :         u_int32_t                       is;
     722             :         int                             port;
     723             : 
     724             :         /* If the card has gone away, this will return 0xffffffff. */
     725           0 :         is = sili_read(sc, SILI_REG_GIS);
     726           0 :         if (is == 0 || is == 0xffffffff)
     727           0 :                 return (0);
     728           0 :         sili_write(sc, SILI_REG_GIS, is);
     729             :         DPRINTF(SILI_D_INTR, "sili_intr, GIS: %08x\n", is);
     730             : 
     731           0 :         while (is & SILI_REG_GIS_PIS_MASK) {
     732           0 :                 port = ffs(is) - 1;
     733           0 :                 sili_port_intr(&sc->sc_ports[port], -1);
     734           0 :                 is &= ~(1 << port);
     735             :         }
     736             : 
     737           0 :         return (1);
     738           0 : }
     739             : 
     740             : int
     741           0 : sili_ports_alloc(struct sili_softc *sc)
     742             : {
     743             :         struct sili_port                *sp;
     744             :         int                             i;
     745             : 
     746           0 :         sc->sc_ports = mallocarray(sc->sc_nports, sizeof(struct sili_port),
     747             :             M_DEVBUF, M_WAITOK | M_ZERO);
     748             : 
     749           0 :         for (i = 0; i < sc->sc_nports; i++) {
     750           0 :                 sp = &sc->sc_ports[i];
     751             : 
     752           0 :                 sp->sp_sc = sc;
     753           0 :                 sp->sp_port = i;
     754             : #ifdef SILI_DEBUG
     755             :                 snprintf(sp->sp_name, sizeof(sp->sp_name), "%s.%d",
     756             :                     DEVNAME(sc), i);
     757             : #endif
     758           0 :                 if (bus_space_subregion(sc->sc_iot_port, sc->sc_ioh_port,
     759           0 :                     SILI_PORT_OFFSET(i), SILI_PORT_SIZE, &sp->sp_ioh) != 0) {
     760           0 :                         printf("%s: unable to create register window "
     761           0 :                             "for port %d\n", DEVNAME(sc), i);
     762             :                         goto freeports;
     763             :                 }
     764             :         }
     765             : 
     766           0 :         return (0);
     767             : 
     768             : freeports:
     769             :         /* bus_space(9) says subregions dont have to be freed */
     770           0 :         free(sp, M_DEVBUF, sc->sc_nports * sizeof(struct sili_port));
     771           0 :         sc->sc_ports = NULL;
     772           0 :         return (1);
     773           0 : }
     774             : 
     775             : void
     776           0 : sili_ports_free(struct sili_softc *sc)
     777             : {
     778             :         struct sili_port                *sp;
     779             :         int                             i;
     780             : 
     781           0 :         for (i = 0; i < sc->sc_nports; i++) {
     782           0 :                 sp = &sc->sc_ports[i];
     783             : 
     784           0 :                 if (sp->sp_ccbs != NULL)
     785           0 :                         sili_ccb_free(sp);
     786             :         }
     787             : 
     788             :         /* bus_space(9) says subregions dont have to be freed */
     789           0 :         free(sc->sc_ports, M_DEVBUF, sc->sc_nports * sizeof(struct sili_port));
     790           0 :         sc->sc_ports = NULL;
     791           0 : }
     792             : 
     793             : int
     794           0 : sili_ccb_alloc(struct sili_port *sp)
     795             : {
     796           0 :         struct sili_softc               *sc = sp->sp_sc;
     797             :         struct sili_ccb                 *ccb;
     798             :         struct sili_prb                 *prb;
     799             :         int                             i;
     800             : 
     801           0 :         TAILQ_INIT(&sp->sp_free_ccbs);
     802           0 :         mtx_init(&sp->sp_free_ccb_mtx, IPL_BIO);
     803           0 :         TAILQ_INIT(&sp->sp_active_ccbs);
     804           0 :         TAILQ_INIT(&sp->sp_deferred_ccbs);
     805             : 
     806           0 :         sp->sp_ccbs = mallocarray(SILI_MAX_CMDS, sizeof(struct sili_ccb),
     807             :             M_DEVBUF, M_WAITOK);
     808           0 :         sp->sp_cmds = sili_dmamem_alloc(sc, SILI_CMD_LEN * SILI_MAX_CMDS,
     809             :             SILI_PRB_ALIGN);
     810           0 :         if (sp->sp_cmds == NULL)
     811             :                 goto free_ccbs;
     812           0 :         sp->sp_scratch = sili_dmamem_alloc(sc, SILI_SCRATCH_LEN, PAGE_SIZE);
     813           0 :         if (sp->sp_scratch == NULL)
     814             :                 goto free_cmds;
     815             : 
     816           0 :         bzero(sp->sp_ccbs, sizeof(struct sili_ccb) * SILI_MAX_CMDS);
     817             : 
     818           0 :         for (i = 0; i < SILI_MAX_CMDS; i++) {
     819           0 :                 ccb = &sp->sp_ccbs[i];
     820           0 :                 ccb->ccb_port = sp;
     821           0 :                 ccb->ccb_cmd = SILI_DMA_KVA(sp->sp_cmds) + i * SILI_CMD_LEN;
     822           0 :                 ccb->ccb_cmd_dva = SILI_DMA_DVA(sp->sp_cmds) + i * SILI_CMD_LEN;
     823           0 :                 if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, SILI_DMA_SEGS,
     824             :                     MAXPHYS, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
     825           0 :                     &ccb->ccb_dmamap) != 0)
     826             :                         goto free_scratch;
     827             : 
     828           0 :                 prb = ccb->ccb_cmd;
     829           0 :                 ccb->ccb_xa.fis = (struct ata_fis_h2d *)&prb->fis;
     830           0 :                 ccb->ccb_xa.packetcmd = ((struct sili_prb_packet *)prb)->cdb;
     831           0 :                 ccb->ccb_xa.tag = i;
     832           0 :                 ccb->ccb_xa.state = ATA_S_COMPLETE;
     833             : 
     834           0 :                 sili_put_ccb(ccb);
     835             :         }
     836             : 
     837           0 :         return (0);
     838             : 
     839             : free_scratch:
     840           0 :         sili_dmamem_free(sc, sp->sp_scratch);
     841             : free_cmds:
     842           0 :         sili_dmamem_free(sc, sp->sp_cmds);
     843             : free_ccbs:
     844           0 :         sili_ccb_free(sp);
     845           0 :         return (1);
     846           0 : }
     847             : 
     848             : void
     849           0 : sili_ccb_free(struct sili_port *sp)
     850             : {
     851           0 :         struct sili_softc               *sc = sp->sp_sc;
     852             :         struct sili_ccb                 *ccb;
     853             : 
     854           0 :         while ((ccb = sili_get_ccb(sp)) != NULL)
     855           0 :                 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
     856             : 
     857           0 :         free(sp->sp_ccbs, M_DEVBUF, 0);
     858           0 :         sp->sp_ccbs = NULL;
     859           0 : }
     860             : 
     861             : struct sili_ccb *
     862           0 : sili_get_ccb(struct sili_port *sp)
     863             : {
     864             :         struct sili_ccb                 *ccb;
     865             : 
     866             :         /*
     867             :          * Don't allow new commands to start while doing PMP error
     868             :          * recovery
     869             :          */
     870           0 :         if (sp->sp_pmp_error_recovery != 0) {
     871           0 :                 return (NULL);
     872             :         }
     873             : 
     874           0 :         mtx_enter(&sp->sp_free_ccb_mtx);
     875           0 :         ccb = TAILQ_FIRST(&sp->sp_free_ccbs);
     876           0 :         if (ccb != NULL) {
     877           0 :                 KASSERT(ccb->ccb_xa.state == ATA_S_PUT);
     878           0 :                 TAILQ_REMOVE(&sp->sp_free_ccbs, ccb, ccb_entry);
     879           0 :                 ccb->ccb_xa.state = ATA_S_SETUP;
     880           0 :         }
     881           0 :         mtx_leave(&sp->sp_free_ccb_mtx);
     882             : 
     883           0 :         return (ccb);
     884           0 : }
     885             : 
     886             : void
     887           0 : sili_put_ccb(struct sili_ccb *ccb)
     888             : {
     889           0 :         struct sili_port                *sp = ccb->ccb_port;
     890             : 
     891             : #ifdef DIAGNOSTIC
     892           0 :         if (ccb->ccb_xa.state != ATA_S_COMPLETE &&
     893           0 :             ccb->ccb_xa.state != ATA_S_TIMEOUT &&
     894           0 :             ccb->ccb_xa.state != ATA_S_ERROR) {
     895           0 :                 printf("%s: invalid ata_xfer state %02x in sili_put_ccb, "
     896           0 :                     "slot %d\n", PORTNAME(sp), ccb->ccb_xa.state,
     897           0 :                     ccb->ccb_xa.tag);
     898           0 :         }
     899             : #endif
     900             : 
     901           0 :         ccb->ccb_xa.state = ATA_S_PUT;
     902           0 :         mtx_enter(&sp->sp_free_ccb_mtx);
     903           0 :         TAILQ_INSERT_TAIL(&sp->sp_free_ccbs, ccb, ccb_entry);
     904           0 :         mtx_leave(&sp->sp_free_ccb_mtx);
     905           0 : }
     906             : 
     907             : struct sili_dmamem *
     908           0 : sili_dmamem_alloc(struct sili_softc *sc, bus_size_t size, bus_size_t align)
     909             : {
     910             :         struct sili_dmamem              *sdm;
     911           0 :         int                             nsegs;
     912             : 
     913           0 :         sdm = malloc(sizeof(*sdm), M_DEVBUF, M_WAITOK | M_ZERO);
     914           0 :         sdm->sdm_size = size;
     915             : 
     916           0 :         if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
     917           0 :             BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &sdm->sdm_map) != 0)
     918             :                 goto sdmfree;
     919             : 
     920           0 :         if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0, &sdm->sdm_seg,
     921           0 :             1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
     922             :                 goto destroy;
     923             : 
     924           0 :         if (bus_dmamem_map(sc->sc_dmat, &sdm->sdm_seg, nsegs, size,
     925           0 :             &sdm->sdm_kva, BUS_DMA_NOWAIT) != 0)
     926             :                 goto free;
     927             : 
     928           0 :         if (bus_dmamap_load(sc->sc_dmat, sdm->sdm_map, sdm->sdm_kva, size,
     929           0 :             NULL, BUS_DMA_NOWAIT) != 0)
     930             :                 goto unmap;
     931             : 
     932           0 :         return (sdm);
     933             : 
     934             : unmap:
     935           0 :         bus_dmamem_unmap(sc->sc_dmat, sdm->sdm_kva, size);
     936             : free:
     937           0 :         bus_dmamem_free(sc->sc_dmat, &sdm->sdm_seg, 1);
     938             : destroy:
     939           0 :         bus_dmamap_destroy(sc->sc_dmat, sdm->sdm_map);
     940             : sdmfree:
     941           0 :         free(sdm, M_DEVBUF, sizeof *sdm);
     942             : 
     943           0 :         return (NULL);
     944           0 : }
     945             : 
     946             : void
     947           0 : sili_dmamem_free(struct sili_softc *sc, struct sili_dmamem *sdm)
     948             : {
     949           0 :         bus_dmamap_unload(sc->sc_dmat, sdm->sdm_map);
     950           0 :         bus_dmamem_unmap(sc->sc_dmat, sdm->sdm_kva, sdm->sdm_size);
     951           0 :         bus_dmamem_free(sc->sc_dmat, &sdm->sdm_seg, 1);
     952           0 :         bus_dmamap_destroy(sc->sc_dmat, sdm->sdm_map);
     953           0 :         free(sdm, M_DEVBUF, sizeof *sdm);
     954           0 : }
     955             : 
     956             : u_int32_t
     957           0 : sili_read(struct sili_softc *sc, bus_size_t r)
     958             : {
     959             :         u_int32_t                       rv;
     960             : 
     961           0 :         bus_space_barrier(sc->sc_iot_global, sc->sc_ioh_global, r, 4,
     962             :             BUS_SPACE_BARRIER_READ);
     963           0 :         rv = bus_space_read_4(sc->sc_iot_global, sc->sc_ioh_global, r);
     964             : 
     965           0 :         return (rv);
     966             : }
     967             : 
     968             : void
     969           0 : sili_write(struct sili_softc *sc, bus_size_t r, u_int32_t v)
     970             : {
     971           0 :         bus_space_write_4(sc->sc_iot_global, sc->sc_ioh_global, r, v);
     972           0 :         bus_space_barrier(sc->sc_iot_global, sc->sc_ioh_global, r, 4,
     973             :             BUS_SPACE_BARRIER_WRITE);
     974           0 : }
     975             : 
     976             : u_int32_t
     977           0 : sili_pread(struct sili_port *sp, bus_size_t r)
     978             : {
     979             :         u_int32_t                       rv;
     980             : 
     981           0 :         bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, 4,
     982             :             BUS_SPACE_BARRIER_READ);
     983           0 :         rv = bus_space_read_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r);
     984             : 
     985           0 :         return (rv);
     986             : }
     987             : 
     988             : void
     989           0 : sili_pwrite(struct sili_port *sp, bus_size_t r, u_int32_t v)
     990             : {
     991           0 :         bus_space_write_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, v);
     992           0 :         bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, 4,
     993             :             BUS_SPACE_BARRIER_WRITE);
     994           0 : }
     995             : 
     996             : int
     997           0 : sili_pwait_eq(struct sili_port *sp, bus_size_t r, u_int32_t mask,
     998             :     u_int32_t value, int timeout)
     999             : {
    1000           0 :         while ((sili_pread(sp, r) & mask) != value) {
    1001           0 :                 if (timeout == 0)
    1002           0 :                         return (0);
    1003             : 
    1004           0 :                 delay(1000);
    1005           0 :                 timeout--;
    1006             :         }
    1007             : 
    1008           0 :         return (1);
    1009           0 : }
    1010             : 
    1011             : int
    1012           0 : sili_pwait_ne(struct sili_port *sp, bus_size_t r, u_int32_t mask,
    1013             :     u_int32_t value, int timeout)
    1014             : {
    1015           0 :         while ((sili_pread(sp, r) & mask) == value) {
    1016           0 :                 if (timeout == 0)
    1017           0 :                         return (0);
    1018             : 
    1019           0 :                 delay(1000);
    1020           0 :                 timeout--;
    1021             :         }
    1022             : 
    1023           0 :         return (1);
    1024           0 : }
    1025             : 
    1026             : void
    1027           0 : sili_post_direct(struct sili_port *sp, u_int slot, void *buf, size_t buflen)
    1028             : {
    1029           0 :         bus_size_t                      r = SILI_PREG_SLOT(slot);
    1030             : 
    1031             : #ifdef DIAGNOSTIC
    1032           0 :         if (buflen != 64 && buflen != 128)
    1033           0 :                 panic("sili_pcopy: buflen of %lu is not 64 or 128", buflen);
    1034             : #endif
    1035             : 
    1036           0 :         bus_space_write_raw_region_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r,
    1037             :             buf, buflen);
    1038           0 :         bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, buflen,
    1039             :             BUS_SPACE_BARRIER_WRITE);
    1040             : 
    1041           0 :         sili_pwrite(sp, SILI_PREG_FIFO, slot);
    1042           0 : }
    1043             : 
    1044             : void
    1045           0 : sili_pread_fis(struct sili_port *sp, u_int slot, struct ata_fis_d2h *fis)
    1046             : {
    1047           0 :         bus_size_t                      r = SILI_PREG_SLOT(slot) + 8;
    1048             : 
    1049           0 :         bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r,
    1050             :             sizeof(struct ata_fis_d2h), BUS_SPACE_BARRIER_READ);
    1051           0 :         bus_space_read_raw_region_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r,
    1052             :             fis, sizeof(struct ata_fis_d2h));
    1053           0 : }
    1054             : 
    1055             : void
    1056           0 : sili_post_indirect(struct sili_port *sp, struct sili_ccb *ccb)
    1057             : {
    1058           0 :         sili_pwrite(sp, SILI_PREG_CAR_LO(ccb->ccb_xa.tag),
    1059           0 :             (u_int32_t)ccb->ccb_cmd_dva);
    1060           0 :         sili_pwrite(sp, SILI_PREG_CAR_HI(ccb->ccb_xa.tag),
    1061           0 :             (u_int32_t)(ccb->ccb_cmd_dva >> 32));
    1062           0 : }
    1063             : 
    1064             : u_int32_t
    1065           0 : sili_signature(struct sili_port *sp, u_int slot)
    1066             : {
    1067             :         u_int32_t                       sig_hi, sig_lo;
    1068             : 
    1069           0 :         sig_hi = sili_pread(sp, SILI_PREG_SIG_HI(slot));
    1070           0 :         sig_hi <<= SILI_PREG_SIG_HI_SHIFT;
    1071           0 :         sig_lo = sili_pread(sp, SILI_PREG_SIG_LO(slot));
    1072           0 :         sig_lo &= SILI_PREG_SIG_LO_MASK;
    1073             : 
    1074           0 :         return (sig_hi | sig_lo);
    1075             : }
    1076             : 
    1077             : void
    1078           0 : sili_dummy_done(struct ata_xfer *xa)
    1079             : {
    1080           0 : }
    1081             : 
    1082             : int
    1083           0 : sili_pmp_portreset(struct sili_softc *sc, int port, int pmp_port)
    1084             : {
    1085             :         struct sili_port        *sp;
    1086           0 :         u_int32_t               data;
    1087             :         int                     loop;
    1088             : 
    1089           0 :         sp = &sc->sc_ports[port];
    1090             :         DPRINTF(SILI_D_VERBOSE, "%s: resetting pmp port %d\n", PORTNAME(sp),
    1091             :             pmp_port);
    1092             : 
    1093           0 :         if (sili_pmp_write(sp, pmp_port, SATA_PMREG_SERR, -1))
    1094             :                 goto err;
    1095           0 :         if (sili_pmp_write(sp, pmp_port, SATA_PMREG_SCTL,
    1096             :             SATA_PM_SCTL_IPM_DISABLED))
    1097             :                 goto err;
    1098           0 :         delay(10000);
    1099             : 
    1100             :         /* enable PHY by writing 1 then 0 to Scontrol DET field, using
    1101             :          * Write Port Multiplier commands
    1102             :          */
    1103           0 :         data = SATA_PM_SCTL_IPM_DISABLED | SATA_PM_SCTL_DET_INIT |
    1104             :             SATA_PM_SCTL_SPD_ANY;
    1105           0 :         if (sili_pmp_write(sp, pmp_port, SATA_PMREG_SCTL, data))
    1106             :                 goto err;
    1107           0 :         delay(100000);
    1108             :         
    1109           0 :         if (sili_pmp_phy_status(sp, pmp_port, &data)) {
    1110           0 :                 printf("%s: cannot clear phy status for PMP probe\n",
    1111           0 :                         PORTNAME(sp));
    1112           0 :                 goto err;
    1113             :         }
    1114             :         
    1115           0 :         sili_pmp_write(sp, pmp_port, SATA_PMREG_SERR, -1);
    1116           0 :         data = SATA_PM_SCTL_IPM_DISABLED | SATA_PM_SCTL_DET_NONE;
    1117           0 :         if (sili_pmp_write(sp, pmp_port, SATA_PMREG_SCTL, data))
    1118             :                 goto err;
    1119           0 :         delay(100000);
    1120             :         
    1121             :         /* wait for PHYRDY by polling SStatus */
    1122           0 :         for (loop = 3; loop; loop--) {
    1123           0 :                 if (sili_pmp_read(sp, pmp_port, SATA_PMREG_SSTS, &data))
    1124             :                         goto err;
    1125           0 :                 if (data & SATA_PM_SSTS_DET)
    1126             :                         break;
    1127           0 :                 delay(100000);
    1128             :         }
    1129           0 :         if (loop == 0) {
    1130             :                 DPRINTF(SILI_D_VERBOSE, "%s.%d: port appears to be unplugged\n",
    1131             :                     PORTNAME(sp), pmp_port);
    1132             :                 goto err;
    1133             :         }
    1134             :         
    1135             :         /* give it a bit more time to complete negotiation */
    1136           0 :         for (loop = 30; loop; loop--) {
    1137           0 :                 if (sili_pmp_read(sp, pmp_port, SATA_PMREG_SSTS, &data))
    1138             :                         goto err;
    1139           0 :                 if ((data & SATA_PM_SSTS_DET) == SATA_PM_SSTS_DET_DEV)
    1140             :                         break;
    1141           0 :                 delay(10000);
    1142             :         }
    1143           0 :         if (loop == 0) {
    1144           0 :                 printf("%s.%d: device may be powered down\n", PORTNAME(sp),
    1145             :                     pmp_port);
    1146           0 :                 goto err;
    1147             :         }
    1148             : 
    1149             :         DPRINTF(SILI_D_VERBOSE, "%s.%d: device detected; SStatus=%08x\n",
    1150             :             PORTNAME(sp), pmp_port, data);
    1151             : 
    1152             :         /* clear the X-bit and all other error bits in Serror (PCSR[1]) */
    1153           0 :         sili_pmp_write(sp, pmp_port, SATA_PMREG_SERR, -1);
    1154           0 :         return (0);
    1155             : 
    1156             : err:
    1157             :         DPRINTF(SILI_D_VERBOSE, "%s.%d: port reset failed\n", PORTNAME(sp),
    1158             :             pmp_port);
    1159           0 :         sili_pmp_write(sp, pmp_port, SATA_PMREG_SERR, -1);
    1160           0 :         return (1);
    1161           0 : }
    1162             : 
    1163             : void
    1164           0 : sili_pmp_op_timeout(void *cookie)
    1165             : {
    1166           0 :         struct sili_ccb *ccb = cookie;
    1167           0 :         struct sili_port *sp = ccb->ccb_port;
    1168             :         int s;
    1169             : 
    1170           0 :         switch (ccb->ccb_xa.state) {
    1171             :         case ATA_S_PENDING:
    1172           0 :                 TAILQ_REMOVE(&sp->sp_active_ccbs, ccb, ccb_entry);
    1173           0 :                 ccb->ccb_xa.state = ATA_S_TIMEOUT;
    1174           0 :                 break;
    1175             :         case ATA_S_ONCHIP:
    1176           0 :                 KASSERT(sp->sp_active == (1 << ccb->ccb_xa.tag));
    1177           0 :                 s = splbio();
    1178           0 :                 sili_port_intr(sp, ccb->ccb_xa.tag);
    1179           0 :                 splx(s);
    1180           0 :                 break;
    1181             :         case ATA_S_ERROR:
    1182             :                 /* don't do anything? */
    1183             :                 break;
    1184             :         default:
    1185           0 :                 panic("%s: sili_pmp_op_timeout: ccb in bad state %d",
    1186           0 :                       PORTNAME(sp), ccb->ccb_xa.state);
    1187             :         }
    1188           0 : }
    1189             : 
    1190             : int
    1191           0 : sili_pmp_softreset(struct sili_softc *sc, int port, int pmp_port)
    1192             : {
    1193             :         struct sili_ccb         *ccb;
    1194             :         struct sili_prb         *prb;
    1195             :         struct sili_port        *sp;
    1196             :         struct ata_fis_h2d      *fis;
    1197           0 :         u_int32_t               data;
    1198             :         u_int32_t               signature;
    1199             : 
    1200           0 :         sp = &sc->sc_ports[port];
    1201             : 
    1202           0 :         ccb = sili_get_ccb(sp);
    1203           0 :         if (ccb == NULL) {
    1204           0 :                 printf("%s: sili_pmp_softreset NULL ccb!\n", PORTNAME(sp));
    1205           0 :                 return (-1);
    1206             :         }
    1207             : 
    1208           0 :         ccb->ccb_xa.flags = ATA_F_POLL | ATA_F_GET_RFIS;
    1209           0 :         ccb->ccb_xa.complete = sili_dummy_done;
    1210           0 :         ccb->ccb_xa.pmp_port = pmp_port;
    1211             :         
    1212           0 :         prb = ccb->ccb_cmd;
    1213           0 :         bzero(prb, sizeof(*prb));
    1214           0 :         fis = (struct ata_fis_h2d *)&prb->fis;
    1215           0 :         fis->flags = pmp_port;
    1216           0 :         prb->control = SILI_PRB_SOFT_RESET;
    1217             : 
    1218           0 :         ccb->ccb_xa.state = ATA_S_PENDING;
    1219             : 
    1220           0 :         if (sili_poll(ccb, 8000, sili_pmp_op_timeout) != 0) {
    1221             :                 DPRINTF(SILI_D_VERBOSE, "%s.%d: softreset FIS failed\n",
    1222             :                     PORTNAME(sp), pmp_port);
    1223             : 
    1224           0 :                 sili_put_ccb(ccb);
    1225             :                 /* don't return a valid device type here so the caller knows
    1226             :                  * it can retry if it wants to
    1227             :                  */
    1228           0 :                 return (-1);
    1229             :         }
    1230             : 
    1231           0 :         signature = ccb->ccb_xa.rfis.sector_count |
    1232           0 :             (ccb->ccb_xa.rfis.lba_low << 8) |
    1233           0 :             (ccb->ccb_xa.rfis.lba_mid << 16) |
    1234           0 :             (ccb->ccb_xa.rfis.lba_high << 24);
    1235             :         DPRINTF(SILI_D_VERBOSE, "%s.%d: signature: %08x\n", PORTNAME(sp),
    1236             :             pmp_port, signature);
    1237             : 
    1238           0 :         sili_put_ccb(ccb);
    1239             : 
    1240             :         /* clear phy status and error bits */
    1241           0 :         if (sili_pmp_phy_status(sp, pmp_port, &data)) {
    1242           0 :                 printf("%s.%d: cannot clear phy status after softreset\n",
    1243           0 :                        PORTNAME(sp), pmp_port);
    1244           0 :         }
    1245           0 :         sili_pmp_write(sp, pmp_port, SATA_PMREG_SERR, -1);
    1246             : 
    1247             :         /* classify the device based on its signature */
    1248           0 :         switch (signature) {
    1249             :         case SATA_SIGNATURE_DISK:
    1250           0 :                 return (ATA_PORT_T_DISK);
    1251             :         case SATA_SIGNATURE_ATAPI:
    1252           0 :                 return (ATA_PORT_T_ATAPI);
    1253             :         case SATA_SIGNATURE_PORT_MULTIPLIER:
    1254           0 :                 return (ATA_PORT_T_NONE);
    1255             :         default:
    1256           0 :                 return (ATA_PORT_T_NONE);
    1257             :         }
    1258           0 : }
    1259             : 
    1260             : u_int32_t
    1261           0 : sili_port_softreset(struct sili_port *sp)
    1262             : {
    1263           0 :         struct sili_prb_softreset       sreset;
    1264             :         u_int32_t                       signature;
    1265             : 
    1266           0 :         bzero(&sreset, sizeof(sreset));
    1267           0 :         sreset.control = htole16(SILI_PRB_SOFT_RESET | SILI_PRB_INTERRUPT_MASK);
    1268           0 :         sreset.fis[1] = SATA_PMP_CONTROL_PORT;
    1269             : 
    1270             :         /* we use slot 0 */
    1271           0 :         sili_post_direct(sp, 0, &sreset, sizeof(sreset));
    1272           0 :         if (!sili_pwait_eq(sp, SILI_PREG_PSS, (1 << 0), 0, 1000)) {
    1273             :                 DPRINTF(SILI_D_VERBOSE, "%s: timed out while waiting for soft "
    1274             :                     "reset\n", PORTNAME(sp));
    1275           0 :                 return (ATA_PORT_T_NONE);
    1276             :         }
    1277             : 
    1278             :         /* Read device signature from command slot. */
    1279           0 :         signature = sili_signature(sp, 0);
    1280             : 
    1281             :         DPRINTF(SILI_D_VERBOSE, "%s: signature 0x%08x\n", PORTNAME(sp),
    1282             :             signature);
    1283             : 
    1284           0 :         switch (signature) {
    1285             :         case SATA_SIGNATURE_DISK:
    1286           0 :                 return (ATA_PORT_T_DISK);
    1287             :         case SATA_SIGNATURE_ATAPI:
    1288           0 :                 return (ATA_PORT_T_ATAPI);
    1289             :         case SATA_SIGNATURE_PORT_MULTIPLIER:
    1290           0 :                 return (ATA_PORT_T_PM);
    1291             :         default:
    1292           0 :                 return (ATA_PORT_T_NONE);
    1293             :         }
    1294           0 : }
    1295             : 
    1296             : int
    1297           0 : sili_ata_probe(void *xsc, int port, int lun)
    1298             : {
    1299           0 :         struct sili_softc               *sc = xsc;
    1300           0 :         struct sili_port                *sp = &sc->sc_ports[port];
    1301             :         int                             port_type;
    1302             : 
    1303             :         /* handle pmp port probes */
    1304           0 :         if (lun != 0) {
    1305             :                 int i;
    1306             :                 int rc;
    1307           0 :                 int pmp_port = lun - 1;
    1308             : 
    1309           0 :                 if (lun > sp->sp_pmp_ports)
    1310           0 :                         return (ATA_PORT_T_NONE);
    1311             : 
    1312           0 :                 for (i = 0; i < 2; i++) {
    1313           0 :                         if (sili_pmp_portreset(sc, port, pmp_port)) {
    1314             :                                 continue;
    1315             :                         }
    1316             : 
    1317             :                         /* small delay between attempts to allow error
    1318             :                          * conditions to settle down.  this doesn't seem
    1319             :                          * to affect portreset operations, just
    1320             :                          * commands sent to the device.
    1321             :                          */
    1322           0 :                         if (i != 0) {
    1323           0 :                                 delay(5000000);
    1324           0 :                         }
    1325             : 
    1326           0 :                         rc = sili_pmp_softreset(sc, port, pmp_port);
    1327           0 :                         switch (rc) {
    1328             :                         case -1:
    1329             :                                 /* possibly try again */
    1330             :                                 break;
    1331             :                         case ATA_PORT_T_DISK:
    1332             :                         case ATA_PORT_T_ATAPI:
    1333             :                                 /* mark this port as active */
    1334           0 :                                 sp->sp_active_pmp_ports |= (1 << pmp_port);
    1335             :                         default:
    1336           0 :                                 return (rc);
    1337             :                         }
    1338             :                 }
    1339             :                 DPRINTF(SILI_D_VERBOSE, "%s.%d: probe failed\n", PORTNAME(sp),
    1340             :                     pmp_port);
    1341           0 :                 return (ATA_PORT_T_NONE);
    1342             :         }
    1343             : 
    1344           0 :         sili_pwrite(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTRESET);
    1345           0 :         delay(10000);
    1346           0 :         sili_pwrite(sp, SILI_PREG_PCC, SILI_PREG_PCC_PORTRESET);
    1347             : 
    1348           0 :         sili_pwrite(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTINIT);
    1349           0 :         if (!sili_pwait_eq(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTRDY,
    1350             :             SILI_PREG_PCS_PORTRDY, 1000)) {
    1351           0 :                 printf("%s: couldn't initialize port\n", PORTNAME(sp));
    1352           0 :                 return (ATA_PORT_T_NONE);
    1353             :         }
    1354             : 
    1355           0 :         sili_pwrite(sp, SILI_PREG_PCC, SILI_PREG_PCC_A32B);
    1356             : 
    1357           0 :         if (!sili_pwait_eq(sp, SILI_PREG_SSTS, SATA_SStatus_DET,
    1358             :             SATA_SStatus_DET_DEV, 2000)) {
    1359             :                 DPRINTF(SILI_D_VERBOSE, "%s: unattached\n", PORTNAME(sp));
    1360           0 :                 return (ATA_PORT_T_NONE);
    1361             :         }
    1362             : 
    1363             :         DPRINTF(SILI_D_VERBOSE, "%s: SSTS 0x%08x\n", PORTNAME(sp),
    1364             :             sili_pread(sp, SILI_PREG_SSTS));
    1365             : 
    1366           0 :         port_type = sili_port_softreset(sp);
    1367           0 :         if (port_type == ATA_PORT_T_NONE)
    1368           0 :                 return (port_type);
    1369             : 
    1370             :         /* allocate port resources */
    1371           0 :         if (sili_ccb_alloc(sp) != 0)
    1372           0 :                 return (ATA_PORT_T_NONE);
    1373             : 
    1374             :         /* do PMP probe now that we can talk to the device */
    1375           0 :         if (port_type == ATA_PORT_T_PM) {
    1376             :                 int i;
    1377             : 
    1378           0 :                 sili_pwrite(sp, SILI_PREG_PCS, SILI_PREG_PCS_PMEN);
    1379             : 
    1380           0 :                 if (sili_pmp_identify(sp, &sp->sp_pmp_ports)) {
    1381           0 :                         return (ATA_PORT_T_NONE);
    1382             :                 }
    1383             : 
    1384             :                 /* reset all the PMP ports to wake devices up */
    1385           0 :                 for (i = 0; i < sp->sp_pmp_ports; i++) {
    1386           0 :                         sili_pmp_portreset(sp->sp_sc, sp->sp_port, i);
    1387             :                 }
    1388           0 :         }
    1389             : 
    1390             :         /* enable port interrupts */
    1391           0 :         sili_write(sc, SILI_REG_GC, sili_read(sc, SILI_REG_GC) | 1 << port);
    1392           0 :         sili_pwrite(sp, SILI_PREG_IES, SILI_PREG_IE_CMDERR |
    1393             :             SILI_PREG_IE_CMDCOMP);
    1394             : 
    1395           0 :         return (port_type);
    1396           0 : }
    1397             : 
    1398             : void
    1399           0 : sili_ata_free(void *xsc, int port, int lun)
    1400             : {
    1401           0 :         struct sili_softc               *sc = xsc;
    1402           0 :         struct sili_port                *sp = &sc->sc_ports[port];
    1403             : 
    1404           0 :         if (lun == 0) {
    1405           0 :                 if (sp->sp_ccbs != NULL)
    1406           0 :                         sili_ccb_free(sp);
    1407             : 
    1408             :                 /* XXX we should do more here */
    1409             :         }
    1410           0 : }
    1411             : 
    1412             : void
    1413           0 : sili_ata_cmd(struct ata_xfer *xa)
    1414             : {
    1415           0 :         struct sili_ccb                 *ccb = (struct sili_ccb *)xa;
    1416           0 :         struct sili_port                *sp = ccb->ccb_port;
    1417           0 :         struct sili_softc               *sc = sp->sp_sc;
    1418             :         struct sili_prb_ata             *ata;
    1419             :         struct sili_prb_packet          *atapi;
    1420             :         struct sili_sge                 *sgl;
    1421             :         int                             sgllen;
    1422             :         int                             s;
    1423             : 
    1424           0 :         KASSERT(xa->state == ATA_S_SETUP || xa->state == ATA_S_TIMEOUT);
    1425             : 
    1426           0 :         if (xa->flags & ATA_F_PACKET) {
    1427           0 :                 atapi = ccb->ccb_cmd;
    1428             : 
    1429           0 :                 if (xa->flags & ATA_F_WRITE)
    1430           0 :                         atapi->control = htole16(SILI_PRB_PACKET_WRITE);
    1431             :                 else
    1432           0 :                         atapi->control = htole16(SILI_PRB_PACKET_READ);
    1433             : 
    1434           0 :                 sgl = atapi->sgl;
    1435             :                 sgllen = nitems(atapi->sgl);
    1436           0 :         } else {
    1437           0 :                 ata = ccb->ccb_cmd;
    1438             : 
    1439           0 :                 ata->control = 0;
    1440             : 
    1441           0 :                 sgl = ata->sgl;
    1442             :                 sgllen = nitems(ata->sgl);
    1443             :         }
    1444             : 
    1445           0 :         if (sili_load(ccb, sgl, sgllen) != 0)
    1446             :                 goto failcmd;
    1447             : 
    1448           0 :         bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_cmds),
    1449             :             xa->tag * SILI_CMD_LEN, SILI_CMD_LEN, BUS_DMASYNC_PREWRITE);
    1450             : 
    1451           0 :         timeout_set(&xa->stimeout, sili_ata_cmd_timeout, ccb);
    1452             : 
    1453           0 :         xa->state = ATA_S_PENDING;
    1454             : 
    1455           0 :         if (xa->flags & ATA_F_POLL)
    1456           0 :                 sili_poll(ccb, xa->timeout, sili_ata_cmd_timeout);
    1457             :         else {
    1458           0 :                 s = splbio();
    1459           0 :                 timeout_add_msec(&xa->stimeout, xa->timeout);
    1460           0 :                 sili_start(sp, ccb);
    1461           0 :                 splx(s);
    1462             :         }
    1463             : 
    1464           0 :         return;
    1465             : 
    1466             : failcmd:
    1467           0 :         s = splbio();
    1468           0 :         xa->state = ATA_S_ERROR;
    1469           0 :         ata_complete(xa);
    1470           0 :         splx(s);
    1471           0 : }
    1472             : 
    1473             : void
    1474           0 : sili_ata_cmd_done(struct sili_ccb *ccb, int defer_completion)
    1475             : {
    1476           0 :         struct sili_port                *sp = ccb->ccb_port;
    1477           0 :         struct sili_softc               *sc = sp->sp_sc;
    1478           0 :         struct ata_xfer                 *xa = &ccb->ccb_xa;
    1479             : 
    1480           0 :         splassert(IPL_BIO);
    1481             : 
    1482           0 :         timeout_del(&xa->stimeout);
    1483             : 
    1484           0 :         bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_cmds),
    1485             :             xa->tag * SILI_CMD_LEN, SILI_CMD_LEN, BUS_DMASYNC_POSTWRITE);
    1486             : 
    1487           0 :         sili_unload(ccb);
    1488             : 
    1489           0 :         TAILQ_REMOVE(&sp->sp_active_ccbs, ccb, ccb_entry);
    1490           0 :         sp->sp_active &= ~(1 << xa->tag);
    1491           0 :         if (sp->sp_err_active & (1 << xa->tag)) {
    1492           0 :                 sp->sp_err_active &= ~(1 << xa->tag);
    1493             :                 DPRINTF(SILI_D_VERBOSE, "%s: slot %d complete, error mask now "
    1494             :                     "%x\n", PORTNAME(sp), xa->tag, sp->sp_err_active);
    1495           0 :         }
    1496             : 
    1497           0 :         if (xa->state == ATA_S_ONCHIP)
    1498           0 :                 xa->state = ATA_S_COMPLETE;
    1499             : #ifdef DIAGNOSTIC
    1500           0 :         else if (xa->state != ATA_S_ERROR && xa->state != ATA_S_TIMEOUT)
    1501           0 :                 printf("%s: invalid ata_xfer state %02x in sili_ata_cmd_done, "
    1502           0 :                     "slot %d\n", PORTNAME(sp), xa->state, xa->tag);
    1503             : #endif
    1504           0 :         if (defer_completion)
    1505           0 :                 TAILQ_INSERT_TAIL(&sp->sp_deferred_ccbs, ccb, ccb_entry);
    1506           0 :         else if (xa->state == ATA_S_COMPLETE)
    1507           0 :                 ata_complete(xa);
    1508             : #ifdef DIAGNOSTIC
    1509             :         else
    1510           0 :                 printf("%s: completion not deferred, but xa->state is %02x?\n",
    1511           0 :                     PORTNAME(sp), xa->state);
    1512             : #endif
    1513           0 : }
    1514             : 
    1515             : void
    1516           0 : sili_ata_cmd_timeout(void *xccb)
    1517             : {
    1518           0 :         struct sili_ccb                 *ccb = xccb;
    1519           0 :         struct sili_port                *sp = ccb->ccb_port;
    1520             :         int                             s;
    1521             : 
    1522           0 :         s = splbio();
    1523           0 :         sili_port_intr(sp, ccb->ccb_xa.tag);
    1524           0 :         splx(s);
    1525           0 : }
    1526             : 
    1527             : int
    1528           0 : sili_load(struct sili_ccb *ccb, struct sili_sge *sgl, int sgllen)
    1529             : {
    1530           0 :         struct sili_port                *sp = ccb->ccb_port;
    1531           0 :         struct sili_softc               *sc = sp->sp_sc;
    1532           0 :         struct ata_xfer                 *xa = &ccb->ccb_xa;
    1533             :         struct sili_sge                 *nsge = sgl, *ce = NULL;
    1534           0 :         bus_dmamap_t                    dmap = ccb->ccb_dmamap;
    1535             :         u_int64_t                       addr;
    1536             :         int                             error;
    1537             :         int                             i;
    1538             : 
    1539           0 :         if (xa->datalen == 0)
    1540           0 :                 return (0);
    1541             : 
    1542           0 :         error = bus_dmamap_load(sc->sc_dmat, dmap, xa->data, xa->datalen, NULL,
    1543             :             (xa->flags & ATA_F_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
    1544           0 :         if (error != 0) {
    1545           0 :                 printf("%s: error %d loading dmamap\n", PORTNAME(sp), error);
    1546           0 :                 return (1);
    1547             :         }
    1548             : 
    1549           0 :         if (dmap->dm_nsegs > sgllen)
    1550           0 :                 ce = &sgl[sgllen - 1];
    1551             : 
    1552           0 :         for (i = 0; i < dmap->dm_nsegs; i++) {
    1553           0 :                 if (nsge == ce) {
    1554           0 :                         nsge++;
    1555             : 
    1556           0 :                         addr = ccb->ccb_cmd_dva;
    1557           0 :                         addr += ((u_int8_t *)nsge - (u_int8_t *)ccb->ccb_cmd);
    1558             : 
    1559           0 :                         ce->addr_lo = htole32((u_int32_t)addr);
    1560           0 :                         ce->addr_hi = htole32((u_int32_t)(addr >> 32));
    1561           0 :                         ce->flags = htole32(SILI_SGE_LNK);
    1562             : 
    1563           0 :                         if ((dmap->dm_nsegs - i) > SILI_SGT_SGLLEN)
    1564           0 :                                 ce += SILI_SGT_SGLLEN;
    1565             :                         else
    1566             :                                 ce = NULL;
    1567             :                 }
    1568             : 
    1569             :                 sgl = nsge;
    1570             : 
    1571           0 :                 addr = dmap->dm_segs[i].ds_addr;
    1572           0 :                 sgl->addr_lo = htole32((u_int32_t)addr);
    1573           0 :                 sgl->addr_hi = htole32((u_int32_t)(addr >> 32));
    1574           0 :                 sgl->data_count = htole32(dmap->dm_segs[i].ds_len);
    1575           0 :                 sgl->flags = 0;
    1576             : 
    1577           0 :                 nsge++;
    1578             :         }
    1579           0 :         sgl->flags |= htole32(SILI_SGE_TRM);
    1580             : 
    1581           0 :         bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
    1582             :             (xa->flags & ATA_F_READ) ? BUS_DMASYNC_PREREAD :
    1583             :             BUS_DMASYNC_PREWRITE);
    1584             : 
    1585           0 :         return (0);
    1586           0 : }
    1587             : 
    1588             : void
    1589           0 : sili_unload(struct sili_ccb *ccb)
    1590             : {
    1591           0 :         struct sili_port                *sp = ccb->ccb_port;
    1592           0 :         struct sili_softc               *sc = sp->sp_sc;
    1593           0 :         struct ata_xfer                 *xa = &ccb->ccb_xa;
    1594           0 :         bus_dmamap_t                    dmap = ccb->ccb_dmamap;
    1595             : 
    1596           0 :         if (xa->datalen == 0)
    1597           0 :                 return;
    1598             : 
    1599           0 :         bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
    1600             :             (xa->flags & ATA_F_READ) ? BUS_DMASYNC_POSTREAD :
    1601             :             BUS_DMASYNC_POSTWRITE);
    1602           0 :         bus_dmamap_unload(sc->sc_dmat, dmap);
    1603             : 
    1604           0 :         if (xa->flags & ATA_F_READ)
    1605           0 :                 xa->resid = xa->datalen - sili_pread(sp,
    1606           0 :                     SILI_PREG_RX_COUNT(xa->tag));
    1607             :         else
    1608           0 :                 xa->resid = 0;
    1609           0 : }
    1610             : 
    1611             : int
    1612           0 : sili_poll(struct sili_ccb *ccb, int timeout, void (*timeout_fn)(void *))
    1613             : {
    1614           0 :         struct sili_port                *sp = ccb->ccb_port;
    1615             :         int                             s;
    1616             : 
    1617           0 :         s = splbio();
    1618           0 :         sili_start(sp, ccb);
    1619           0 :         do {
    1620           0 :                 if (sili_port_intr(sp, -1) & (1 << ccb->ccb_xa.tag)) {
    1621           0 :                         splx(s);
    1622           0 :                         return (ccb->ccb_xa.state != ATA_S_COMPLETE);
    1623             :                 }
    1624             : 
    1625           0 :                 delay(1000);
    1626           0 :         } while (--timeout > 0);
    1627             : 
    1628             :         /* Run timeout while at splbio, otherwise sili_intr could interfere. */
    1629           0 :         if (timeout_fn != NULL)
    1630           0 :                 timeout_fn(ccb);
    1631             : 
    1632           0 :         splx(s);
    1633             : 
    1634           0 :         return (1);
    1635           0 : }
    1636             : 
    1637             : void
    1638           0 : sili_start(struct sili_port *sp, struct sili_ccb *ccb)
    1639             : {
    1640           0 :         int                             slot = ccb->ccb_xa.tag;
    1641             : 
    1642           0 :         splassert(IPL_BIO);
    1643           0 :         KASSERT(ccb->ccb_xa.state == ATA_S_PENDING);
    1644           0 :         KASSERT(sp->sp_pmp_error_recovery == 0);
    1645             : 
    1646           0 :         TAILQ_INSERT_TAIL(&sp->sp_active_ccbs, ccb, ccb_entry);
    1647           0 :         sp->sp_active |= 1 << slot;
    1648           0 :         ccb->ccb_xa.state = ATA_S_ONCHIP;
    1649             : 
    1650           0 :         sili_post_indirect(sp, ccb);
    1651           0 : }
    1652             : 
    1653             : int
    1654           0 : sili_read_ncq_error(struct sili_port *sp, int *err_slotp, int pmp_port)
    1655             : {
    1656           0 :         struct sili_softc               *sc = sp->sp_sc;
    1657           0 :         struct sili_prb_ata             read_10h;
    1658             :         u_int64_t                       addr;
    1659             :         struct ata_fis_h2d              *fis;
    1660             :         struct ata_log_page_10h         *log;
    1661             :         struct sili_ccb                 *ccb;
    1662             :         int                             rc;
    1663             : 
    1664           0 :         sili_pwrite(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTINIT);
    1665           0 :         if (!sili_pwait_eq(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTRDY,
    1666             :             SILI_PREG_PCS_PORTRDY, 1000)) {
    1667           0 :                 printf("%s: couldn't ready port during log page read\n",
    1668           0 :                     PORTNAME(sp));
    1669           0 :                 return (1);
    1670             :         }
    1671             : 
    1672             :         /* READ LOG EXT 10h into scratch space */
    1673           0 :         bzero(&read_10h, sizeof(read_10h));
    1674           0 :         read_10h.control = htole16(SILI_PRB_INTERRUPT_MASK);
    1675             : 
    1676           0 :         addr = SILI_DMA_DVA(sp->sp_scratch);
    1677           0 :         read_10h.sgl[0].addr_lo = htole32((u_int32_t)addr);
    1678           0 :         read_10h.sgl[0].addr_hi = htole32((u_int32_t)(addr >> 32));
    1679           0 :         read_10h.sgl[0].data_count = htole32(512);
    1680           0 :         read_10h.sgl[0].flags = htole32(SILI_SGE_TRM);
    1681             : 
    1682           0 :         fis = (struct ata_fis_h2d *)read_10h.fis;
    1683           0 :         fis->type = ATA_FIS_TYPE_H2D;
    1684           0 :         fis->flags = ATA_H2D_FLAGS_CMD | pmp_port;
    1685           0 :         fis->command = ATA_C_READ_LOG_EXT;
    1686           0 :         fis->lba_low = 0x10;         /* queued error log page (10h) */
    1687           0 :         fis->sector_count = 1;               /* number of sectors (1) */
    1688           0 :         fis->sector_count_exp = 0;
    1689           0 :         fis->lba_mid = 0;            /* starting offset */
    1690           0 :         fis->lba_mid_exp = 0;
    1691           0 :         fis->device = 0;
    1692             : 
    1693           0 :         bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_scratch), 0,
    1694             :             512, BUS_DMASYNC_PREREAD);
    1695             : 
    1696             :         /* issue read and poll for completion */
    1697           0 :         sili_post_direct(sp, 0, &read_10h, sizeof(read_10h));
    1698           0 :         rc = sili_pwait_eq(sp, SILI_PREG_PSS, (1 << 0), 0, 1000);
    1699             : 
    1700           0 :         bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_scratch), 0,
    1701             :             512, BUS_DMASYNC_POSTREAD);
    1702             : 
    1703           0 :         if (!rc) {
    1704             :                 DPRINTF(SILI_D_VERBOSE, "%s: timed out while waiting for log "
    1705             :                     "page read\n", PORTNAME(sp));
    1706           0 :                 return (1);
    1707             :         }
    1708             : 
    1709             :         /* Extract failed register set and tags from the scratch space. */
    1710           0 :         log = (struct ata_log_page_10h *)SILI_DMA_KVA(sp->sp_scratch);
    1711           0 :         if (ISSET(log->err_regs.type, ATA_LOG_10H_TYPE_NOTQUEUED)) {
    1712             :                 /* Not queued bit was set - wasn't an NCQ error? */
    1713           0 :                 printf("%s: read NCQ error page, but not an NCQ error?\n",
    1714           0 :                     PORTNAME(sp));
    1715           0 :                 return (1);
    1716             :         }
    1717             : 
    1718             :         /* Copy back the log record as a D2H register FIS. */
    1719           0 :         *err_slotp = log->err_regs.type & ATA_LOG_10H_TYPE_TAG_MASK;
    1720             : 
    1721           0 :         ccb = &sp->sp_ccbs[*err_slotp];
    1722           0 :         memcpy(&ccb->ccb_xa.rfis, &log->err_regs, sizeof(struct ata_fis_d2h));
    1723           0 :         ccb->ccb_xa.rfis.type = ATA_FIS_TYPE_D2H;
    1724           0 :         ccb->ccb_xa.rfis.flags = 0;
    1725             : 
    1726           0 :         return (0);
    1727           0 : }
    1728             : 
    1729             : struct ata_xfer *
    1730           0 : sili_ata_get_xfer(void *xsc, int port)
    1731             : {
    1732           0 :         struct sili_softc               *sc = xsc;
    1733           0 :         struct sili_port                *sp = &sc->sc_ports[port];
    1734             :         struct sili_ccb                 *ccb;
    1735             : 
    1736           0 :         ccb = sili_get_ccb(sp);
    1737           0 :         if (ccb == NULL) {
    1738           0 :                 printf("%s: sili_ata_get_xfer NULL ccb!\n", PORTNAME(sp));
    1739           0 :                 return (NULL);
    1740             :         }
    1741             : 
    1742           0 :         bzero(ccb->ccb_cmd, SILI_CMD_LEN);
    1743             : 
    1744           0 :         return ((struct ata_xfer *)ccb);
    1745           0 : }
    1746             : 
    1747             : void
    1748           0 : sili_ata_put_xfer(struct ata_xfer *xa)
    1749             : {
    1750           0 :         struct sili_ccb                 *ccb = (struct sili_ccb *)xa;
    1751             : 
    1752           0 :         sili_put_ccb(ccb);
    1753           0 : }
    1754             : 
    1755             : /* PMP register ops */
    1756             : int
    1757           0 : sili_pmp_read(struct sili_port *sp, int target, int which, u_int32_t *datap)
    1758             : {
    1759             :         struct sili_ccb *ccb;
    1760             :         struct sili_prb *prb;
    1761             :         struct ata_fis_h2d *fis;
    1762             :         int error;
    1763             : 
    1764           0 :         ccb = sili_get_ccb(sp);
    1765           0 :         if (ccb == NULL) {
    1766           0 :                 printf("%s: sili_pmp_read NULL ccb!\n", PORTNAME(sp));
    1767           0 :                 return (1);
    1768             :         }
    1769           0 :         ccb->ccb_xa.flags = ATA_F_POLL | ATA_F_GET_RFIS;
    1770           0 :         ccb->ccb_xa.complete = sili_dummy_done;
    1771           0 :         ccb->ccb_xa.pmp_port = SATA_PMP_CONTROL_PORT;
    1772           0 :         ccb->ccb_xa.state = ATA_S_PENDING;
    1773             :         
    1774           0 :         prb = ccb->ccb_cmd;
    1775           0 :         bzero(prb, sizeof(*prb));
    1776           0 :         fis = (struct ata_fis_h2d *)&prb->fis;
    1777           0 :         fis->type = ATA_FIS_TYPE_H2D;
    1778           0 :         fis->flags = ATA_H2D_FLAGS_CMD | SATA_PMP_CONTROL_PORT;
    1779           0 :         fis->command = ATA_C_READ_PM;
    1780           0 :         fis->features = which;
    1781           0 :         fis->device = target | ATA_H2D_DEVICE_LBA;
    1782           0 :         fis->control = ATA_FIS_CONTROL_4BIT;
    1783             : 
    1784           0 :         if (sili_poll(ccb, 1000, sili_pmp_op_timeout) != 0) {
    1785           0 :                 printf("sili_pmp_read(%d, %d) failed\n", target, which);
    1786             :                 error = 1;
    1787           0 :         } else {
    1788           0 :                 *datap = ccb->ccb_xa.rfis.sector_count |
    1789           0 :                     (ccb->ccb_xa.rfis.lba_low << 8) |
    1790           0 :                     (ccb->ccb_xa.rfis.lba_mid << 16) |
    1791           0 :                     (ccb->ccb_xa.rfis.lba_high << 24);
    1792             :                 error = 0;
    1793             :         }
    1794           0 :         sili_put_ccb(ccb);
    1795           0 :         return (error);
    1796           0 : }
    1797             : 
    1798             : int
    1799           0 : sili_pmp_write(struct sili_port *sp, int target, int which, u_int32_t data)
    1800             : {
    1801             :         struct sili_ccb *ccb;
    1802             :         struct sili_prb *prb;
    1803             :         struct ata_fis_h2d *fis;
    1804             :         int error;
    1805             : 
    1806           0 :         ccb = sili_get_ccb(sp);
    1807           0 :         if (ccb == NULL) {
    1808           0 :                 printf("%s: sili_pmp_write NULL ccb!\n", PORTNAME(sp));
    1809           0 :                 return (1);
    1810             :         }
    1811           0 :         ccb->ccb_xa.complete = sili_dummy_done;
    1812           0 :         ccb->ccb_xa.flags = ATA_F_POLL;
    1813           0 :         ccb->ccb_xa.pmp_port = SATA_PMP_CONTROL_PORT;
    1814           0 :         ccb->ccb_xa.state = ATA_S_PENDING;
    1815             : 
    1816           0 :         prb = ccb->ccb_cmd;
    1817           0 :         bzero(prb, sizeof(*prb));
    1818           0 :         fis = (struct ata_fis_h2d *)&prb->fis;
    1819           0 :         fis->type = ATA_FIS_TYPE_H2D;
    1820           0 :         fis->flags = ATA_H2D_FLAGS_CMD | SATA_PMP_CONTROL_PORT;
    1821           0 :         fis->command = ATA_C_WRITE_PM;
    1822           0 :         fis->features = which;
    1823           0 :         fis->device = target | ATA_H2D_DEVICE_LBA;
    1824           0 :         fis->sector_count = (u_int8_t)data;
    1825           0 :         fis->lba_low = (u_int8_t)(data >> 8);
    1826           0 :         fis->lba_mid = (u_int8_t)(data >> 16);
    1827           0 :         fis->lba_high = (u_int8_t)(data >> 24);
    1828           0 :         fis->control = ATA_FIS_CONTROL_4BIT;
    1829             : 
    1830           0 :         error = sili_poll(ccb, 1000, sili_pmp_op_timeout);
    1831           0 :         sili_put_ccb(ccb);
    1832           0 :         return (error);
    1833           0 : }
    1834             : 
    1835             : int
    1836           0 : sili_pmp_phy_status(struct sili_port *sp, int target, u_int32_t *datap)
    1837             : {
    1838             :         int error;
    1839             : 
    1840           0 :         error = sili_pmp_read(sp, target, SATA_PMREG_SSTS, datap);
    1841           0 :         if (error == 0)
    1842           0 :                 error = sili_pmp_write(sp, target, SATA_PMREG_SERR, -1);
    1843           0 :         if (error)
    1844           0 :                 *datap = 0;
    1845             : 
    1846           0 :         return (error);
    1847             : }
    1848             : 
    1849             : int
    1850           0 : sili_pmp_identify(struct sili_port *sp, int *ret_nports)
    1851             : {
    1852           0 :         u_int32_t chipid;
    1853           0 :         u_int32_t rev;
    1854           0 :         u_int32_t nports;
    1855           0 :         u_int32_t features;
    1856           0 :         u_int32_t enabled;
    1857             : 
    1858           0 :         if (sili_pmp_read(sp, 15, 0, &chipid) ||
    1859           0 :             sili_pmp_read(sp, 15, 1, &rev) ||
    1860           0 :             sili_pmp_read(sp, 15, 2, &nports) ||
    1861           0 :             sili_pmp_read(sp, 15, SATA_PMREG_FEA, &features) ||
    1862           0 :             sili_pmp_read(sp, 15, SATA_PMREG_FEAEN, &enabled)) {
    1863           0 :                 printf("%s: port multiplier identification failed\n",
    1864           0 :                     PORTNAME(sp));
    1865           0 :                 return (1);
    1866             :         }
    1867             : 
    1868           0 :         nports &= 0x0F;
    1869             : 
    1870             :         /* ignore SEMB port on SiI3726 port multiplier chips */
    1871           0 :         if (chipid == 0x37261095) {
    1872           0 :                 nports--;
    1873           0 :         }
    1874             : 
    1875           0 :         printf("%s: port multiplier found: chip=%08x rev=0x%b nports=%d, "
    1876           0 :             "features: 0x%b, enabled: 0x%b\n", PORTNAME(sp), chipid, rev,
    1877           0 :             SATA_PFMT_PM_REV, nports, features, SATA_PFMT_PM_FEA, enabled,
    1878             :             SATA_PFMT_PM_FEA);
    1879             : 
    1880           0 :         *ret_nports = nports;
    1881           0 :         return (0);
    1882           0 : }

Generated by: LCOV version 1.13