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

          Line data    Source code
       1             : /*      $OpenBSD: atascsi.c,v 1.129 2017/08/23 05:13:01 jsg 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/buf.h>
      24             : #include <sys/kernel.h>
      25             : #include <sys/malloc.h>
      26             : #include <sys/device.h>
      27             : #include <sys/queue.h>
      28             : #include <sys/pool.h>
      29             : 
      30             : #include <scsi/scsi_all.h>
      31             : #include <scsi/scsi_disk.h>
      32             : #include <scsi/scsiconf.h>
      33             : 
      34             : #include <dev/ata/atascsi.h>
      35             : #include <dev/ata/pmreg.h>
      36             : 
      37             : struct atascsi_port;
      38             : 
      39             : struct atascsi {
      40             :         struct device           *as_dev;
      41             :         void                    *as_cookie;
      42             : 
      43             :         struct atascsi_host_port **as_host_ports;
      44             : 
      45             :         struct atascsi_methods  *as_methods;
      46             :         struct scsi_adapter     as_switch;
      47             :         struct scsi_link        as_link;
      48             :         struct scsibus_softc    *as_scsibus;
      49             : 
      50             :         int                     as_capability;
      51             :         int                     as_ncqdepth;
      52             : };
      53             : 
      54             : /*
      55             :  * atascsi_host_port is a port attached to the host controller, and
      56             :  * only holds the details relevant to the host controller.
      57             :  * atascsi_port is any port, including ports on port multipliers, and
      58             :  * it holds details of the device attached to the port.
      59             :  *
      60             :  * When there is a port multiplier attached to a port, the ahp_ports
      61             :  * array in the atascsi_host_port struct contains one atascsi_port for
      62             :  * each port, and one for the control port (port 15).  The index into
      63             :  * the array is the LUN used to address the port.  For the control port,
      64             :  * the LUN is 0, and for the port multiplier ports, the LUN is the
      65             :  * port number plus one.
      66             :  *
      67             :  * When there is no port multiplier attached to a port, the ahp_ports
      68             :  * array contains a single entry for the device.  The LUN and port number
      69             :  * for this entry are both 0.
      70             :  */
      71             : 
      72             : struct atascsi_host_port {
      73             :         struct scsi_iopool      ahp_iopool;
      74             :         struct atascsi          *ahp_as;
      75             :         int                     ahp_port;
      76             :         int                     ahp_nports;
      77             : 
      78             :         struct atascsi_port     **ahp_ports;
      79             : };
      80             : 
      81             : struct atascsi_port {
      82             :         struct ata_identify     ap_identify;
      83             :         struct atascsi_host_port *ap_host_port;
      84             :         struct atascsi          *ap_as;
      85             :         int                     ap_pmp_port;
      86             :         int                     ap_type;
      87             :         int                     ap_ncqdepth;
      88             :         int                     ap_features;
      89             : #define ATA_PORT_F_NCQ                  0x1
      90             : #define ATA_PORT_F_TRIM                 0x2
      91             : };
      92             : 
      93             : void            atascsi_cmd(struct scsi_xfer *);
      94             : int             atascsi_probe(struct scsi_link *);
      95             : void            atascsi_free(struct scsi_link *);
      96             : 
      97             : /* template */
      98             : struct scsi_adapter atascsi_switch = {
      99             :         atascsi_cmd,            /* scsi_cmd */
     100             :         scsi_minphys,           /* scsi_minphys */
     101             :         atascsi_probe,          /* dev_probe */
     102             :         atascsi_free,           /* dev_free */
     103             :         NULL,                   /* ioctl */
     104             : };
     105             : 
     106             : void            ata_swapcopy(void *, void *, size_t);
     107             : 
     108             : void            atascsi_disk_cmd(struct scsi_xfer *);
     109             : void            atascsi_disk_cmd_done(struct ata_xfer *);
     110             : void            atascsi_disk_inq(struct scsi_xfer *);
     111             : void            atascsi_disk_inquiry(struct scsi_xfer *);
     112             : void            atascsi_disk_vpd_supported(struct scsi_xfer *);
     113             : void            atascsi_disk_vpd_serial(struct scsi_xfer *);
     114             : void            atascsi_disk_vpd_ident(struct scsi_xfer *);
     115             : void            atascsi_disk_vpd_ata(struct scsi_xfer *);
     116             : void            atascsi_disk_vpd_limits(struct scsi_xfer *);
     117             : void            atascsi_disk_vpd_info(struct scsi_xfer *);
     118             : void            atascsi_disk_vpd_thin(struct scsi_xfer *);
     119             : void            atascsi_disk_write_same_16(struct scsi_xfer *);
     120             : void            atascsi_disk_write_same_16_done(struct ata_xfer *);
     121             : void            atascsi_disk_unmap(struct scsi_xfer *);
     122             : void            atascsi_disk_unmap_task(void *);
     123             : void            atascsi_disk_unmap_done(struct ata_xfer *);
     124             : void            atascsi_disk_capacity(struct scsi_xfer *);
     125             : void            atascsi_disk_capacity16(struct scsi_xfer *);
     126             : void            atascsi_disk_sync(struct scsi_xfer *);
     127             : void            atascsi_disk_sync_done(struct ata_xfer *);
     128             : void            atascsi_disk_sense(struct scsi_xfer *);
     129             : void            atascsi_disk_start_stop(struct scsi_xfer *);
     130             : void            atascsi_disk_start_stop_done(struct ata_xfer *);
     131             : 
     132             : void            atascsi_atapi_cmd(struct scsi_xfer *);
     133             : void            atascsi_atapi_cmd_done(struct ata_xfer *);
     134             : 
     135             : void            atascsi_pmp_cmd(struct scsi_xfer *);
     136             : void            atascsi_pmp_cmd_done(struct ata_xfer *);
     137             : void            atascsi_pmp_sense(struct scsi_xfer *xs);
     138             : void            atascsi_pmp_inq(struct scsi_xfer *xs);
     139             : 
     140             : 
     141             : void            atascsi_passthru_12(struct scsi_xfer *);
     142             : void            atascsi_passthru_16(struct scsi_xfer *);
     143             : int             atascsi_passthru_map(struct scsi_xfer *, u_int8_t, u_int8_t);
     144             : void            atascsi_passthru_done(struct ata_xfer *);
     145             : 
     146             : void            atascsi_done(struct scsi_xfer *, int);
     147             : 
     148             : void            ata_exec(struct atascsi *, struct ata_xfer *);
     149             : 
     150             : void            ata_polled_complete(struct ata_xfer *);
     151             : int             ata_polled(struct ata_xfer *);
     152             : 
     153             : u_int64_t       ata_identify_blocks(struct ata_identify *);
     154             : u_int           ata_identify_blocksize(struct ata_identify *);
     155             : u_int           ata_identify_block_l2p_exp(struct ata_identify *);
     156             : u_int           ata_identify_block_logical_align(struct ata_identify *);
     157             : 
     158             : void            *atascsi_io_get(void *);
     159             : void            atascsi_io_put(void *, void *);
     160             : struct atascsi_port * atascsi_lookup_port(struct scsi_link *);
     161             : 
     162             : int             atascsi_port_identify(struct atascsi_port *,
     163             :                     struct ata_identify *);
     164             : int             atascsi_port_set_features(struct atascsi_port *, int, int);
     165             : 
     166             : 
     167             : struct atascsi *
     168           0 : atascsi_attach(struct device *self, struct atascsi_attach_args *aaa)
     169             : {
     170           0 :         struct scsibus_attach_args      saa;
     171             :         struct atascsi                  *as;
     172             : 
     173           0 :         as = malloc(sizeof(*as), M_DEVBUF, M_WAITOK | M_ZERO);
     174             : 
     175           0 :         as->as_dev = self;
     176           0 :         as->as_cookie = aaa->aaa_cookie;
     177           0 :         as->as_methods = aaa->aaa_methods;
     178           0 :         as->as_capability = aaa->aaa_capability;
     179           0 :         as->as_ncqdepth = aaa->aaa_ncmds;
     180             : 
     181             :         /* copy from template and modify for ourselves */
     182           0 :         as->as_switch = atascsi_switch;
     183           0 :         if (aaa->aaa_minphys != NULL)
     184           0 :                 as->as_switch.scsi_minphys = aaa->aaa_minphys;
     185             : 
     186             :         /* fill in our scsi_link */
     187           0 :         as->as_link.adapter = &as->as_switch;
     188           0 :         as->as_link.adapter_softc = as;
     189           0 :         as->as_link.adapter_buswidth = aaa->aaa_nports;
     190           0 :         as->as_link.luns = SATA_PMP_MAX_PORTS;
     191           0 :         as->as_link.adapter_target = aaa->aaa_nports;
     192           0 :         as->as_link.openings = 1;
     193             : 
     194           0 :         as->as_host_ports = mallocarray(aaa->aaa_nports,
     195             :             sizeof(struct atascsi_host_port *), M_DEVBUF, M_WAITOK | M_ZERO);
     196             : 
     197           0 :         bzero(&saa, sizeof(saa));
     198           0 :         saa.saa_sc_link = &as->as_link;
     199             : 
     200             :         /* stash the scsibus so we can do hotplug on it */
     201           0 :         as->as_scsibus = (struct scsibus_softc *)config_found(self, &saa,
     202             :             scsiprint);
     203             : 
     204           0 :         return (as);
     205           0 : }
     206             : 
     207             : int
     208           0 : atascsi_detach(struct atascsi *as, int flags)
     209             : {
     210             :         int                             rv;
     211             : 
     212           0 :         rv = config_detach((struct device *)as->as_scsibus, flags);
     213           0 :         if (rv != 0)
     214           0 :                 return (rv);
     215             : 
     216           0 :         free(as->as_host_ports, M_DEVBUF, 0);
     217           0 :         free(as, M_DEVBUF, sizeof(*as));
     218             : 
     219           0 :         return (0);
     220           0 : }
     221             : 
     222             : int
     223           0 : atascsi_probe_dev(struct atascsi *as, int port, int lun)
     224             : {
     225           0 :         if (lun == 0) {
     226           0 :                 return (scsi_probe_target(as->as_scsibus, port));
     227             :         } else {
     228           0 :                 return (scsi_probe_lun(as->as_scsibus, port, lun));
     229             :         }
     230           0 : }
     231             : 
     232             : int
     233           0 : atascsi_detach_dev(struct atascsi *as, int port, int lun, int flags)
     234             : {
     235           0 :         if (lun == 0) {
     236           0 :                 return (scsi_detach_target(as->as_scsibus, port, flags));
     237             :         } else {
     238           0 :                 return (scsi_detach_lun(as->as_scsibus, port, lun, flags));
     239             :         }
     240           0 : }
     241             : 
     242             : struct atascsi_port *
     243           0 : atascsi_lookup_port(struct scsi_link *link)
     244             : {
     245           0 :         struct atascsi                  *as = link->adapter_softc;
     246             :         struct atascsi_host_port        *ahp;
     247             : 
     248           0 :         if (link->target >= as->as_link.adapter_buswidth)
     249           0 :                 return (NULL);
     250             : 
     251           0 :         ahp = as->as_host_ports[link->target];
     252           0 :         if (link->lun >= ahp->ahp_nports)
     253           0 :                 return (NULL);
     254             : 
     255           0 :         return (ahp->ahp_ports[link->lun]);
     256           0 : }
     257             : 
     258             : int
     259           0 : atascsi_probe(struct scsi_link *link)
     260             : {
     261           0 :         struct atascsi                  *as = link->adapter_softc;
     262             :         struct atascsi_host_port        *ahp;
     263             :         struct atascsi_port             *ap;
     264             :         struct ata_xfer                 *xa;
     265             :         struct ata_identify             *identify;
     266             :         int                             port, type, qdepth;
     267             :         int                             rv;
     268             :         u_int16_t                       cmdset;
     269             :         u_int16_t                       validinfo, ultradma;
     270             :         int                             i, xfermode = -1;
     271             : 
     272           0 :         port = link->target;
     273           0 :         if (port >= as->as_link.adapter_buswidth)
     274           0 :                 return (ENXIO);
     275             : 
     276             :         /* if this is a PMP port, check it's valid */
     277           0 :         if (link->lun > 0) {
     278           0 :                 if (link->lun >= as->as_host_ports[port]->ahp_nports)
     279           0 :                         return (ENXIO);
     280             :         }
     281             : 
     282           0 :         type = as->as_methods->ata_probe(as->as_cookie, port, link->lun);
     283           0 :         switch (type) {
     284             :         case ATA_PORT_T_DISK:
     285             :                 break;
     286             :         case ATA_PORT_T_ATAPI:
     287           0 :                 link->flags |= SDEV_ATAPI;
     288           0 :                 link->quirks |= SDEV_ONLYBIG;
     289           0 :                 break;
     290             :         case ATA_PORT_T_PM:
     291           0 :                 if (link->lun != 0) {
     292           0 :                         printf("%s.%d.%d: Port multipliers cannot be nested\n",
     293           0 :                             as->as_dev->dv_xname, port, link->lun);
     294             :                         rv = ENODEV;
     295           0 :                         goto unsupported;
     296             :                 }
     297             :                 break;
     298             :         default:
     299             :                 rv = ENODEV;
     300           0 :                 goto unsupported;
     301             :         }
     302             : 
     303           0 :         ap = malloc(sizeof(*ap), M_DEVBUF, M_WAITOK | M_ZERO);
     304           0 :         ap->ap_as = as;
     305             : 
     306           0 :         if (link->lun == 0) {
     307           0 :                 ahp = malloc(sizeof(*ahp), M_DEVBUF, M_WAITOK | M_ZERO);
     308           0 :                 ahp->ahp_as = as;
     309           0 :                 ahp->ahp_port = port;
     310             : 
     311           0 :                 scsi_iopool_init(&ahp->ahp_iopool, ahp, atascsi_io_get,
     312             :                     atascsi_io_put);
     313             : 
     314           0 :                 as->as_host_ports[port] = ahp;
     315             : 
     316           0 :                 if (type == ATA_PORT_T_PM) {
     317           0 :                         ahp->ahp_nports = SATA_PMP_MAX_PORTS;
     318           0 :                         ap->ap_pmp_port = SATA_PMP_CONTROL_PORT;
     319           0 :                 } else {
     320           0 :                         ahp->ahp_nports = 1;
     321           0 :                         ap->ap_pmp_port = 0;
     322             :                 }
     323           0 :                 ahp->ahp_ports = mallocarray(ahp->ahp_nports,
     324             :                     sizeof(struct atascsi_port *), M_DEVBUF, M_WAITOK | M_ZERO);
     325           0 :         } else {
     326           0 :                 ahp = as->as_host_ports[port];
     327           0 :                 ap->ap_pmp_port = link->lun - 1;
     328             :         }
     329             : 
     330           0 :         ap->ap_host_port = ahp;
     331           0 :         ap->ap_type = type;
     332             : 
     333           0 :         link->pool = &ahp->ahp_iopool;
     334             : 
     335             :         /* fetch the device info, except for port multipliers */
     336           0 :         if (type != ATA_PORT_T_PM) {
     337             : 
     338             :                 /* devices attached to port multipliers tend not to be
     339             :                  * spun up at this point, and sometimes this prevents
     340             :                  * identification from working, so we retry a few times
     341             :                  * with a fairly long delay.
     342             :                  */
     343             : 
     344           0 :                 identify = dma_alloc(sizeof(*identify), PR_WAITOK | PR_ZERO);
     345             : 
     346           0 :                 int count = (link->lun > 0) ? 6 : 2;
     347           0 :                 while (count--) {
     348           0 :                         rv = atascsi_port_identify(ap, identify);
     349           0 :                         if (rv == 0) {
     350           0 :                                 ap->ap_identify = *identify;
     351           0 :                                 break;
     352             :                         }
     353           0 :                         if (count > 0)
     354           0 :                                 delay(5000000);
     355             :                 }
     356             : 
     357           0 :                 dma_free(identify, sizeof(*identify));
     358             : 
     359           0 :                 if (rv != 0) {
     360           0 :                         goto error;
     361             :                 }
     362           0 :         }
     363             : 
     364           0 :         ahp->ahp_ports[link->lun] = ap;
     365             : 
     366           0 :         if (type != ATA_PORT_T_DISK)
     367           0 :                 return (0);
     368             : 
     369             :         /*
     370             :          * Early SATA drives (as well as PATA drives) need to have
     371             :          * their transfer mode set properly, otherwise commands that
     372             :          * use DMA will time out.
     373             :          */
     374           0 :         validinfo = letoh16(ap->ap_identify.validinfo);
     375           0 :         if (ISSET(validinfo, ATA_ID_VALIDINFO_ULTRADMA)) {
     376           0 :                 ultradma = letoh16(ap->ap_identify.ultradma);
     377           0 :                 for (i = 7; i >= 0; i--) {
     378           0 :                         if (ultradma & (1 << i)) {
     379           0 :                                 xfermode = ATA_SF_XFERMODE_UDMA | i;
     380           0 :                                 break;
     381             :                         }
     382             :                 }
     383             :         }
     384           0 :         if (xfermode != -1)
     385           0 :                 (void)atascsi_port_set_features(ap, ATA_SF_XFERMODE, xfermode);
     386             : 
     387           0 :         if (as->as_capability & ASAA_CAP_NCQ &&
     388           0 :             ISSET(letoh16(ap->ap_identify.satacap), ATA_SATACAP_NCQ) &&
     389           0 :             (link->lun == 0 || as->as_capability & ASAA_CAP_PMP_NCQ)) {
     390           0 :                 ap->ap_ncqdepth = ATA_QDEPTH(letoh16(ap->ap_identify.qdepth));
     391           0 :                 qdepth = MIN(ap->ap_ncqdepth, as->as_ncqdepth);
     392           0 :                 if (ISSET(as->as_capability, ASAA_CAP_NEEDS_RESERVED))
     393           0 :                         qdepth--;
     394             : 
     395           0 :                 if (qdepth > 1) {
     396           0 :                         SET(ap->ap_features, ATA_PORT_F_NCQ);
     397             : 
     398             :                         /* Raise the number of openings */
     399           0 :                         link->openings = qdepth;
     400             : 
     401             :                         /*
     402             :                          * XXX for directly attached devices, throw away any xfers
     403             :                          * that have tag numbers higher than what the device supports.
     404             :                          */
     405           0 :                         if (link->lun == 0) {
     406           0 :                                 while (qdepth--) {
     407           0 :                                         xa = scsi_io_get(&ahp->ahp_iopool, SCSI_NOSLEEP);
     408           0 :                                         if (xa->tag < link->openings) {
     409           0 :                                                 xa->state = ATA_S_COMPLETE;
     410           0 :                                                 scsi_io_put(&ahp->ahp_iopool, xa);
     411           0 :                                         }
     412             :                                 }
     413             :                         }
     414             :                 }
     415             :         }
     416             : 
     417           0 :         if (ISSET(letoh16(ap->ap_identify.data_set_mgmt), 
     418             :             ATA_ID_DATA_SET_MGMT_TRIM))
     419           0 :                 SET(ap->ap_features, ATA_PORT_F_TRIM);
     420             : 
     421           0 :         cmdset = letoh16(ap->ap_identify.cmdset82);
     422             : 
     423             :         /* Enable write cache if supported */
     424           0 :         if (ISSET(cmdset, ATA_IDENTIFY_WRITECACHE)) {
     425             :                 /* We don't care if it fails. */
     426           0 :                 (void)atascsi_port_set_features(ap, ATA_SF_WRITECACHE_EN, 0);
     427           0 :         }
     428             : 
     429             :         /* Enable read lookahead if supported */
     430           0 :         if (ISSET(cmdset, ATA_IDENTIFY_LOOKAHEAD)) {
     431             :                 /* We don't care if it fails. */
     432           0 :                 (void)atascsi_port_set_features(ap, ATA_SF_LOOKAHEAD_EN, 0);
     433           0 :         }
     434             : 
     435             :         /*
     436             :          * FREEZE LOCK the device so malicous users can't lock it on us.
     437             :          * As there is no harm in issuing this to devices that don't
     438             :          * support the security feature set we just send it, and don't bother
     439             :          * checking if the device sends a command abort to tell us it doesn't
     440             :          * support it
     441             :          */
     442           0 :         xa = scsi_io_get(&ahp->ahp_iopool, SCSI_NOSLEEP);
     443           0 :         if (xa == NULL)
     444           0 :                 panic("no free xfers on a new port");
     445           0 :         xa->fis->command = ATA_C_SEC_FREEZE_LOCK;
     446           0 :         xa->fis->flags = ATA_H2D_FLAGS_CMD | ap->ap_pmp_port;
     447           0 :         xa->flags = ATA_F_POLL;
     448           0 :         xa->timeout = 1000;
     449           0 :         xa->complete = ata_polled_complete;
     450           0 :         xa->pmp_port = ap->ap_pmp_port;
     451           0 :         xa->atascsi_private = &ahp->ahp_iopool;
     452           0 :         ata_exec(as, xa);
     453           0 :         ata_polled(xa); /* we dont care if it doesnt work */
     454             : 
     455           0 :         return (0);
     456             : error:
     457           0 :         free(ap, M_DEVBUF, sizeof(*ap));
     458             : unsupported:
     459             : 
     460           0 :         as->as_methods->ata_free(as->as_cookie, port, link->lun);
     461           0 :         return (rv);
     462           0 : }
     463             : 
     464             : void
     465           0 : atascsi_free(struct scsi_link *link)
     466             : {
     467           0 :         struct atascsi                  *as = link->adapter_softc;
     468             :         struct atascsi_host_port        *ahp;
     469             :         struct atascsi_port             *ap;
     470             :         int                             port;
     471             : 
     472           0 :         port = link->target;
     473           0 :         if (port >= as->as_link.adapter_buswidth)
     474           0 :                 return;
     475             : 
     476           0 :         ahp = as->as_host_ports[port];
     477           0 :         if (ahp == NULL)
     478           0 :                 return;
     479             : 
     480           0 :         if (link->lun >= ahp->ahp_nports)
     481           0 :                 return;
     482             : 
     483           0 :         ap = ahp->ahp_ports[link->lun];
     484           0 :         free(ap, M_DEVBUF, sizeof(*ap));
     485           0 :         ahp->ahp_ports[link->lun] = NULL;
     486             : 
     487           0 :         as->as_methods->ata_free(as->as_cookie, port, link->lun);
     488             : 
     489           0 :         if (link->lun == ahp->ahp_nports - 1) {
     490             :                 /* we've already freed all of ahp->ahp_ports, now
     491             :                  * free ahp itself.  this relies on the order luns are
     492             :                  * detached in scsi_detach_target().
     493             :                  */
     494           0 :                 free(ahp, M_DEVBUF, sizeof(*ahp));
     495           0 :                 as->as_host_ports[port] = NULL;
     496           0 :         }
     497           0 : }
     498             : 
     499             : void
     500           0 : atascsi_cmd(struct scsi_xfer *xs)
     501             : {
     502           0 :         struct scsi_link        *link = xs->sc_link;
     503             :         struct atascsi_port     *ap;
     504             : 
     505           0 :         ap = atascsi_lookup_port(link);
     506           0 :         if (ap == NULL) {
     507           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
     508           0 :                 return;
     509             :         }
     510             : 
     511           0 :         switch (ap->ap_type) {
     512             :         case ATA_PORT_T_DISK:
     513           0 :                 atascsi_disk_cmd(xs);
     514           0 :                 break;
     515             :         case ATA_PORT_T_ATAPI:
     516           0 :                 atascsi_atapi_cmd(xs);
     517           0 :                 break;
     518             :         case ATA_PORT_T_PM:
     519           0 :                 atascsi_pmp_cmd(xs);
     520           0 :                 break;
     521             : 
     522             :         case ATA_PORT_T_NONE:
     523             :         default:
     524           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
     525           0 :                 break;
     526             :         }
     527           0 : }
     528             : 
     529             : void
     530           0 : atascsi_disk_cmd(struct scsi_xfer *xs)
     531             : {
     532           0 :         struct scsi_link        *link = xs->sc_link;
     533           0 :         struct atascsi          *as = link->adapter_softc;
     534             :         struct atascsi_port     *ap;
     535           0 :         struct ata_xfer         *xa = xs->io;
     536             :         int                     flags = 0;
     537             :         struct ata_fis_h2d      *fis;
     538           0 :         u_int64_t               lba;
     539           0 :         u_int32_t               sector_count;
     540             : 
     541           0 :         ap = atascsi_lookup_port(link);
     542             : 
     543           0 :         switch (xs->cmd->opcode) {
     544             :         case READ_COMMAND:
     545             :         case READ_BIG:
     546             :         case READ_12:
     547             :         case READ_16:
     548             :                 flags = ATA_F_READ;
     549           0 :                 break;
     550             :         case WRITE_COMMAND:
     551             :         case WRITE_BIG:
     552             :         case WRITE_12:
     553             :         case WRITE_16:
     554             :                 flags = ATA_F_WRITE;
     555             :                 /* deal with io outside the switch */
     556           0 :                 break;
     557             : 
     558             :         case WRITE_SAME_16:
     559           0 :                 atascsi_disk_write_same_16(xs);
     560           0 :                 return;
     561             :         case UNMAP:
     562           0 :                 atascsi_disk_unmap(xs);
     563           0 :                 return;
     564             : 
     565             :         case SYNCHRONIZE_CACHE:
     566           0 :                 atascsi_disk_sync(xs);
     567           0 :                 return;
     568             :         case REQUEST_SENSE:
     569           0 :                 atascsi_disk_sense(xs);
     570           0 :                 return;
     571             :         case INQUIRY:
     572           0 :                 atascsi_disk_inq(xs);
     573           0 :                 return;
     574             :         case READ_CAPACITY:
     575           0 :                 atascsi_disk_capacity(xs);
     576           0 :                 return;
     577             :         case READ_CAPACITY_16:
     578           0 :                 atascsi_disk_capacity16(xs);
     579           0 :                 return;
     580             : 
     581             :         case ATA_PASSTHRU_12:
     582           0 :                 atascsi_passthru_12(xs);
     583           0 :                 return;
     584             :         case ATA_PASSTHRU_16:
     585           0 :                 atascsi_passthru_16(xs);
     586           0 :                 return;
     587             : 
     588             :         case START_STOP:
     589           0 :                 atascsi_disk_start_stop(xs);
     590           0 :                 return;
     591             : 
     592             :         case TEST_UNIT_READY:
     593             :         case PREVENT_ALLOW:
     594           0 :                 atascsi_done(xs, XS_NOERROR);
     595           0 :                 return;
     596             : 
     597             :         default:
     598           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
     599           0 :                 return;
     600             :         }
     601             : 
     602           0 :         xa->flags = flags;
     603           0 :         scsi_cmd_rw_decode(xs->cmd, &lba, &sector_count);
     604           0 :         if ((lba >> 48) != 0 || (sector_count >> 16) != 0) {
     605           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
     606           0 :                 return;
     607             :         }
     608             : 
     609           0 :         fis = xa->fis;
     610             : 
     611           0 :         fis->flags = ATA_H2D_FLAGS_CMD | ap->ap_pmp_port;
     612           0 :         fis->lba_low = lba & 0xff;
     613           0 :         fis->lba_mid = (lba >> 8) & 0xff;
     614           0 :         fis->lba_high = (lba >> 16) & 0xff;
     615             : 
     616           0 :         if (ISSET(ap->ap_features, ATA_PORT_F_NCQ) &&
     617           0 :             (xa->tag < ap->ap_ncqdepth) &&
     618           0 :             !(xs->flags & SCSI_POLL)) {
     619             :                 /* Use NCQ */
     620           0 :                 xa->flags |= ATA_F_NCQ;
     621           0 :                 fis->command = (xa->flags & ATA_F_WRITE) ?
     622             :                     ATA_C_WRITE_FPDMA : ATA_C_READ_FPDMA;
     623           0 :                 fis->device = ATA_H2D_DEVICE_LBA;
     624           0 :                 fis->lba_low_exp = (lba >> 24) & 0xff;
     625           0 :                 fis->lba_mid_exp = (lba >> 32) & 0xff;
     626           0 :                 fis->lba_high_exp = (lba >> 40) & 0xff;
     627           0 :                 fis->sector_count = xa->tag << 3;
     628           0 :                 fis->features = sector_count & 0xff;
     629           0 :                 fis->features_exp = (sector_count >> 8) & 0xff;
     630           0 :         } else if (sector_count > 0x100 || lba > 0xfffffff) {
     631             :                 /* Use LBA48 */
     632           0 :                 fis->command = (xa->flags & ATA_F_WRITE) ?
     633             :                     ATA_C_WRITEDMA_EXT : ATA_C_READDMA_EXT;
     634           0 :                 fis->device = ATA_H2D_DEVICE_LBA;
     635           0 :                 fis->lba_low_exp = (lba >> 24) & 0xff;
     636           0 :                 fis->lba_mid_exp = (lba >> 32) & 0xff;
     637           0 :                 fis->lba_high_exp = (lba >> 40) & 0xff;
     638           0 :                 fis->sector_count = sector_count & 0xff;
     639           0 :                 fis->sector_count_exp = (sector_count >> 8) & 0xff;
     640           0 :         } else {
     641             :                 /* Use LBA */
     642           0 :                 fis->command = (xa->flags & ATA_F_WRITE) ?
     643             :                     ATA_C_WRITEDMA : ATA_C_READDMA;
     644           0 :                 fis->device = ATA_H2D_DEVICE_LBA | ((lba >> 24) & 0x0f);
     645           0 :                 fis->sector_count = sector_count & 0xff;
     646             :         }
     647             : 
     648           0 :         xa->data = xs->data;
     649           0 :         xa->datalen = xs->datalen;
     650           0 :         xa->complete = atascsi_disk_cmd_done;
     651           0 :         xa->timeout = xs->timeout;
     652           0 :         xa->pmp_port = ap->ap_pmp_port;
     653           0 :         xa->atascsi_private = xs;
     654           0 :         if (xs->flags & SCSI_POLL)
     655           0 :                 xa->flags |= ATA_F_POLL;
     656             : 
     657           0 :         ata_exec(as, xa);
     658           0 : }
     659             : 
     660             : void
     661           0 : atascsi_disk_cmd_done(struct ata_xfer *xa)
     662             : {
     663           0 :         struct scsi_xfer        *xs = xa->atascsi_private;
     664             : 
     665           0 :         switch (xa->state) {
     666             :         case ATA_S_COMPLETE:
     667           0 :                 xs->error = XS_NOERROR;
     668           0 :                 break;
     669             :         case ATA_S_ERROR:
     670             :                 /* fake sense? */
     671           0 :                 xs->error = XS_DRIVER_STUFFUP;
     672           0 :                 break;
     673             :         case ATA_S_TIMEOUT:
     674           0 :                 xs->error = XS_TIMEOUT;
     675           0 :                 break;
     676             :         default:
     677           0 :                 panic("atascsi_disk_cmd_done: unexpected ata_xfer state (%d)",
     678           0 :                     xa->state);
     679             :         }
     680             : 
     681           0 :         xs->resid = xa->resid;
     682             : 
     683           0 :         scsi_done(xs);
     684           0 : }
     685             : 
     686             : void
     687           0 : atascsi_disk_inq(struct scsi_xfer *xs)
     688             : {
     689           0 :         struct scsi_inquiry     *inq = (struct scsi_inquiry *)xs->cmd;
     690             : 
     691           0 :         if (xs->cmdlen != sizeof(*inq)) {
     692           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
     693           0 :                 return;
     694             :         }
     695             : 
     696           0 :         if (ISSET(inq->flags, SI_EVPD)) {
     697           0 :                 switch (inq->pagecode) {
     698             :                 case SI_PG_SUPPORTED:
     699           0 :                         atascsi_disk_vpd_supported(xs);
     700           0 :                         break;
     701             :                 case SI_PG_SERIAL:
     702           0 :                         atascsi_disk_vpd_serial(xs);
     703           0 :                         break;
     704             :                 case SI_PG_DEVID:
     705           0 :                         atascsi_disk_vpd_ident(xs);
     706           0 :                         break;
     707             :                 case SI_PG_ATA:
     708           0 :                         atascsi_disk_vpd_ata(xs);
     709           0 :                         break;
     710             :                 case SI_PG_DISK_LIMITS:
     711           0 :                         atascsi_disk_vpd_limits(xs);
     712           0 :                         break;
     713             :                 case SI_PG_DISK_INFO:
     714           0 :                         atascsi_disk_vpd_info(xs);
     715           0 :                         break;
     716             :                 case SI_PG_DISK_THIN:
     717           0 :                         atascsi_disk_vpd_thin(xs);
     718           0 :                         break;
     719             :                 default:
     720           0 :                         atascsi_done(xs, XS_DRIVER_STUFFUP);
     721           0 :                         break;
     722             :                 }
     723             :         } else
     724           0 :                 atascsi_disk_inquiry(xs);
     725           0 : }
     726             : 
     727             : void
     728           0 : atascsi_disk_inquiry(struct scsi_xfer *xs)
     729             : {
     730           0 :         struct scsi_inquiry_data inq;
     731           0 :         struct scsi_link        *link = xs->sc_link;
     732             :         struct atascsi_port     *ap;
     733             : 
     734           0 :         ap = atascsi_lookup_port(link);
     735             : 
     736           0 :         bzero(&inq, sizeof(inq));
     737             : 
     738           0 :         inq.device = T_DIRECT;
     739           0 :         inq.version = 0x05; /* SPC-3 */
     740           0 :         inq.response_format = 2;
     741           0 :         inq.additional_length = 32;
     742           0 :         inq.flags |= SID_CmdQue;
     743           0 :         bcopy("ATA     ", inq.vendor, sizeof(inq.vendor));
     744           0 :         ata_swapcopy(ap->ap_identify.model, inq.product,
     745             :             sizeof(inq.product));
     746           0 :         ata_swapcopy(ap->ap_identify.firmware, inq.revision,
     747             :             sizeof(inq.revision));
     748             : 
     749           0 :         bcopy(&inq, xs->data, MIN(sizeof(inq), xs->datalen));
     750             : 
     751           0 :         atascsi_done(xs, XS_NOERROR);
     752           0 : }
     753             : 
     754             : void
     755           0 : atascsi_disk_vpd_supported(struct scsi_xfer *xs)
     756             : {
     757           0 :         struct {
     758             :                 struct scsi_vpd_hdr     hdr;
     759             :                 u_int8_t                list[7];
     760             :         }                       pg;
     761           0 :         struct scsi_link        *link = xs->sc_link;
     762             :         struct atascsi_port     *ap;
     763             :         int                     fat;
     764             : 
     765           0 :         ap = atascsi_lookup_port(link);
     766           0 :         fat = ISSET(ap->ap_features, ATA_PORT_F_TRIM) ? 0 : 1;
     767             : 
     768           0 :         bzero(&pg, sizeof(pg));
     769             : 
     770           0 :         pg.hdr.device = T_DIRECT;
     771           0 :         pg.hdr.page_code = SI_PG_SUPPORTED;
     772           0 :         _lto2b(sizeof(pg.list) - fat, pg.hdr.page_length);
     773           0 :         pg.list[0] = SI_PG_SUPPORTED;
     774           0 :         pg.list[1] = SI_PG_SERIAL;
     775           0 :         pg.list[2] = SI_PG_DEVID;
     776           0 :         pg.list[3] = SI_PG_ATA;
     777           0 :         pg.list[4] = SI_PG_DISK_LIMITS;
     778           0 :         pg.list[5] = SI_PG_DISK_INFO;
     779           0 :         pg.list[6] = SI_PG_DISK_THIN; /* "trimmed" if fat. get it? tehe. */
     780             : 
     781           0 :         bcopy(&pg, xs->data, MIN(sizeof(pg) - fat, xs->datalen));
     782             : 
     783           0 :         atascsi_done(xs, XS_NOERROR);
     784           0 : }
     785             : 
     786             : void
     787           0 : atascsi_disk_vpd_serial(struct scsi_xfer *xs)
     788             : {
     789           0 :         struct scsi_link        *link = xs->sc_link;
     790             :         struct atascsi_port     *ap;
     791           0 :         struct scsi_vpd_serial  pg;
     792             : 
     793           0 :         ap = atascsi_lookup_port(link);
     794           0 :         bzero(&pg, sizeof(pg));
     795             : 
     796           0 :         pg.hdr.device = T_DIRECT;
     797           0 :         pg.hdr.page_code = SI_PG_SERIAL;
     798           0 :         _lto2b(sizeof(ap->ap_identify.serial), pg.hdr.page_length);
     799           0 :         ata_swapcopy(ap->ap_identify.serial, pg.serial,
     800             :             sizeof(ap->ap_identify.serial));
     801             : 
     802           0 :         bcopy(&pg, xs->data, MIN(sizeof(pg), xs->datalen));
     803             : 
     804           0 :         atascsi_done(xs, XS_NOERROR);
     805           0 : }
     806             : 
     807             : void
     808           0 : atascsi_disk_vpd_ident(struct scsi_xfer *xs)
     809             : {
     810           0 :         struct scsi_link        *link = xs->sc_link;
     811             :         struct atascsi_port     *ap;
     812           0 :         struct {
     813             :                 struct scsi_vpd_hdr     hdr;
     814             :                 struct scsi_vpd_devid_hdr devid_hdr;
     815             :                 u_int8_t                devid[68];
     816             :         }                       pg;
     817             :         u_int8_t                *p;
     818             :         size_t                  pg_len;
     819             : 
     820           0 :         ap = atascsi_lookup_port(link);
     821           0 :         bzero(&pg, sizeof(pg));
     822           0 :         if (letoh16(ap->ap_identify.features87) & ATA_ID_F87_WWN) {
     823             :                 pg_len = 8;
     824             : 
     825           0 :                 pg.devid_hdr.pi_code = VPD_DEVID_CODE_BINARY;
     826           0 :                 pg.devid_hdr.flags = VPD_DEVID_ASSOC_LU | VPD_DEVID_TYPE_NAA;
     827             : 
     828           0 :                 ata_swapcopy(&ap->ap_identify.naa_ieee_oui, pg.devid, pg_len);
     829           0 :         } else {
     830             :                 pg_len = 68;
     831             : 
     832           0 :                 pg.devid_hdr.pi_code = VPD_DEVID_CODE_ASCII;
     833           0 :                 pg.devid_hdr.flags = VPD_DEVID_ASSOC_LU | VPD_DEVID_TYPE_T10;
     834             : 
     835           0 :                 p = pg.devid;
     836           0 :                 bcopy("ATA     ", p, 8);
     837           0 :                 p += 8;
     838           0 :                 ata_swapcopy(ap->ap_identify.model, p,
     839             :                     sizeof(ap->ap_identify.model));
     840           0 :                 p += sizeof(ap->ap_identify.model);
     841           0 :                 ata_swapcopy(ap->ap_identify.serial, p,
     842             :                     sizeof(ap->ap_identify.serial));
     843             :         }
     844             : 
     845           0 :         pg.devid_hdr.len = pg_len;
     846           0 :         pg_len += sizeof(pg.devid_hdr);
     847             : 
     848           0 :         pg.hdr.device = T_DIRECT;
     849           0 :         pg.hdr.page_code = SI_PG_DEVID;
     850           0 :         _lto2b(pg_len, pg.hdr.page_length);
     851           0 :         pg_len += sizeof(pg.hdr);
     852             : 
     853           0 :         bcopy(&pg, xs->data, MIN(pg_len, xs->datalen));
     854             : 
     855           0 :         atascsi_done(xs, XS_NOERROR);
     856           0 : }
     857             : 
     858             : void
     859           0 : atascsi_disk_vpd_ata(struct scsi_xfer *xs)
     860             : {
     861           0 :         struct scsi_link        *link = xs->sc_link;
     862             :         struct atascsi_port     *ap;
     863           0 :         struct scsi_vpd_ata     pg;
     864             : 
     865           0 :         ap = atascsi_lookup_port(link);
     866           0 :         bzero(&pg, sizeof(pg));
     867             : 
     868           0 :         pg.hdr.device = T_DIRECT;
     869           0 :         pg.hdr.page_code = SI_PG_ATA;
     870           0 :         _lto2b(sizeof(pg) - sizeof(pg.hdr), pg.hdr.page_length);
     871             : 
     872           0 :         memset(pg.sat_vendor, ' ', sizeof(pg.sat_vendor));
     873           0 :         memcpy(pg.sat_vendor, "OpenBSD",
     874             :             MIN(strlen("OpenBSD"), sizeof(pg.sat_vendor)));
     875           0 :         memset(pg.sat_product, ' ', sizeof(pg.sat_product));
     876           0 :         memcpy(pg.sat_product, "atascsi",
     877             :             MIN(strlen("atascsi"), sizeof(pg.sat_product)));
     878           0 :         memset(pg.sat_revision, ' ', sizeof(pg.sat_revision));
     879           0 :         memcpy(pg.sat_revision, osrelease,
     880             :             MIN(strlen(osrelease), sizeof(pg.sat_revision)));
     881             : 
     882             :         /* XXX device signature */
     883             : 
     884           0 :         switch (ap->ap_type) {
     885             :         case ATA_PORT_T_DISK:
     886           0 :                 pg.command_code = VPD_ATA_COMMAND_CODE_ATA;
     887           0 :                 break;
     888             :         case ATA_PORT_T_ATAPI:
     889           0 :                 pg.command_code = VPD_ATA_COMMAND_CODE_ATAPI;
     890           0 :                 break;
     891             :         }
     892             : 
     893           0 :         memcpy(pg.identify, &ap->ap_identify, sizeof(pg.identify));
     894             : 
     895           0 :         bcopy(&pg, xs->data, MIN(sizeof(pg), xs->datalen));
     896             : 
     897           0 :         atascsi_done(xs, XS_NOERROR);
     898           0 : }
     899             : 
     900             : void
     901           0 : atascsi_disk_vpd_limits(struct scsi_xfer *xs)
     902             : {
     903           0 :         struct scsi_link        *link = xs->sc_link;
     904             :         struct atascsi_port     *ap;
     905           0 :         struct scsi_vpd_disk_limits pg;
     906             : 
     907           0 :         ap = atascsi_lookup_port(link);
     908           0 :         bzero(&pg, sizeof(pg));
     909           0 :         pg.hdr.device = T_DIRECT;
     910           0 :         pg.hdr.page_code = SI_PG_DISK_LIMITS;
     911           0 :         _lto2b(SI_PG_DISK_LIMITS_LEN_THIN, pg.hdr.page_length);
     912             : 
     913           0 :         _lto2b(1 << ata_identify_block_l2p_exp(&ap->ap_identify),
     914           0 :             pg.optimal_xfer_granularity);
     915             : 
     916           0 :         if (ISSET(ap->ap_features, ATA_PORT_F_TRIM)) {
     917             :                 /*
     918             :                  * ATA only supports 65535 blocks per TRIM descriptor, so
     919             :                  * avoid having to split UNMAP descriptors and overflow the page
     920             :                  * limit by using that as a max.
     921             :                  */
     922           0 :                 _lto4b(ATA_DSM_TRIM_MAX_LEN, pg.max_unmap_lba_count);
     923           0 :                 _lto4b(512 / 8, pg.max_unmap_desc_count);
     924           0 :         }
     925             : 
     926           0 :         bcopy(&pg, xs->data, MIN(sizeof(pg), xs->datalen));
     927             : 
     928           0 :         atascsi_done(xs, XS_NOERROR);
     929           0 : }
     930             : 
     931             : void
     932           0 : atascsi_disk_vpd_info(struct scsi_xfer *xs)
     933             : {
     934           0 :         struct scsi_link        *link = xs->sc_link;
     935             :         struct atascsi_port     *ap;
     936           0 :         struct scsi_vpd_disk_info pg;
     937             : 
     938           0 :         ap = atascsi_lookup_port(link);
     939           0 :         bzero(&pg, sizeof(pg));
     940           0 :         pg.hdr.device = T_DIRECT;
     941           0 :         pg.hdr.page_code = SI_PG_DISK_INFO;
     942           0 :         _lto2b(sizeof(pg) - sizeof(pg.hdr), pg.hdr.page_length);
     943             : 
     944           0 :         _lto2b(letoh16(ap->ap_identify.rpm), pg.rpm);
     945           0 :         pg.form_factor = letoh16(ap->ap_identify.form) & ATA_ID_FORM_MASK;
     946             : 
     947           0 :         bcopy(&pg, xs->data, MIN(sizeof(pg), xs->datalen));
     948             : 
     949           0 :         atascsi_done(xs, XS_NOERROR);
     950           0 : }
     951             : 
     952             : void
     953           0 : atascsi_disk_vpd_thin(struct scsi_xfer *xs)
     954             : {
     955           0 :         struct scsi_link        *link = xs->sc_link;
     956             :         struct atascsi_port     *ap;
     957           0 :         struct scsi_vpd_disk_thin pg;
     958             : 
     959           0 :         ap = atascsi_lookup_port(link);
     960           0 :         if (!ISSET(ap->ap_features, ATA_PORT_F_TRIM)) {
     961           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
     962           0 :                 return;
     963             :         }
     964             : 
     965           0 :         bzero(&pg, sizeof(pg));
     966           0 :         pg.hdr.device = T_DIRECT;
     967           0 :         pg.hdr.page_code = SI_PG_DISK_THIN;
     968           0 :         _lto2b(sizeof(pg) - sizeof(pg.hdr), pg.hdr.page_length);
     969             : 
     970           0 :         pg.flags = VPD_DISK_THIN_TPU | VPD_DISK_THIN_TPWS;
     971             : 
     972           0 :         bcopy(&pg, xs->data, MIN(sizeof(pg), xs->datalen));
     973             : 
     974           0 :         atascsi_done(xs, XS_NOERROR);
     975           0 : }
     976             : 
     977             : void
     978           0 : atascsi_disk_write_same_16(struct scsi_xfer *xs)
     979             : {
     980           0 :         struct scsi_link        *link = xs->sc_link;
     981           0 :         struct atascsi          *as = link->adapter_softc;
     982             :         struct atascsi_port     *ap;
     983             :         struct scsi_write_same_16 *cdb;
     984           0 :         struct ata_xfer         *xa = xs->io;
     985             :         struct ata_fis_h2d      *fis;
     986             :         u_int64_t               lba;
     987             :         u_int32_t               length;
     988             :         u_int64_t               desc;
     989             : 
     990           0 :         if (xs->cmdlen != sizeof(*cdb)) {
     991           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
     992           0 :                 return;
     993             :         }
     994             : 
     995           0 :         ap = atascsi_lookup_port(link);
     996           0 :         cdb = (struct scsi_write_same_16 *)xs->cmd;
     997             : 
     998           0 :         if (!ISSET(cdb->flags, WRITE_SAME_F_UNMAP) ||
     999           0 :            !ISSET(ap->ap_features, ATA_PORT_F_TRIM)) {
    1000             :                 /* generate sense data */
    1001           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1002           0 :                 return;
    1003             :         }
    1004             : 
    1005           0 :         if (xs->datalen < 512) {
    1006             :                 /* generate sense data */
    1007           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1008           0 :                 return;
    1009             :         }
    1010             : 
    1011           0 :         lba = _8btol(cdb->lba);
    1012           0 :         length = _4btol(cdb->length);
    1013             : 
    1014           0 :         if (length > ATA_DSM_TRIM_MAX_LEN) {
    1015             :                 /* XXX we dont support requests over 65535 blocks */
    1016           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1017           0 :                 return;
    1018             :         }
    1019             : 
    1020           0 :         xa->data = xs->data;
    1021           0 :         xa->datalen = 512;
    1022           0 :         xa->flags = ATA_F_WRITE;
    1023           0 :         xa->pmp_port = ap->ap_pmp_port;
    1024           0 :         if (xs->flags & SCSI_POLL)
    1025           0 :                 xa->flags |= ATA_F_POLL;
    1026           0 :         xa->complete = atascsi_disk_write_same_16_done;
    1027           0 :         xa->atascsi_private = xs;
    1028           0 :         xa->timeout = (xs->timeout < 45000) ? 45000 : xs->timeout;
    1029             : 
    1030             :         /* TRIM sends a list of blocks to discard in the databuf. */
    1031           0 :         memset(xa->data, 0, xa->datalen);
    1032           0 :         desc = htole64(ATA_DSM_TRIM_DESC(lba, length));
    1033           0 :         memcpy(xa->data, &desc, sizeof(desc));
    1034             : 
    1035           0 :         fis = xa->fis;
    1036           0 :         fis->flags = ATA_H2D_FLAGS_CMD | ap->ap_pmp_port;
    1037           0 :         fis->command = ATA_C_DSM;
    1038           0 :         fis->features = ATA_DSM_TRIM;
    1039           0 :         fis->sector_count = 1;
    1040             : 
    1041           0 :         ata_exec(as, xa);
    1042           0 : }
    1043             : 
    1044             : void
    1045           0 : atascsi_disk_write_same_16_done(struct ata_xfer *xa)
    1046             : {
    1047           0 :         struct scsi_xfer        *xs = xa->atascsi_private;
    1048             : 
    1049           0 :         switch (xa->state) {
    1050             :         case ATA_S_COMPLETE:
    1051           0 :                 xs->error = XS_NOERROR;
    1052           0 :                 break;
    1053             :         case ATA_S_ERROR:
    1054           0 :                 xs->error = XS_DRIVER_STUFFUP;
    1055           0 :                 break;
    1056             :         case ATA_S_TIMEOUT:
    1057           0 :                 xs->error = XS_TIMEOUT;
    1058           0 :                 break;
    1059             : 
    1060             :         default:
    1061           0 :                 panic("atascsi_disk_write_same_16_done: "
    1062           0 :                     "unexpected ata_xfer state (%d)", xa->state);
    1063             :         }
    1064             : 
    1065           0 :         scsi_done(xs);
    1066           0 : }
    1067             : 
    1068             : void
    1069           0 : atascsi_disk_unmap(struct scsi_xfer *xs)
    1070             : {
    1071           0 :         struct ata_xfer         *xa = xs->io;
    1072             :         struct scsi_unmap       *cdb;
    1073             :         struct scsi_unmap_data  *unmap;
    1074             :         u_int                   len;
    1075             : 
    1076           0 :         if (ISSET(xs->flags, SCSI_POLL) || xs->cmdlen != sizeof(*cdb))
    1077           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1078             : 
    1079           0 :         cdb = (struct scsi_unmap *)xs->cmd;
    1080           0 :         len = _2btol(cdb->list_len);
    1081           0 :         if (xs->datalen != len || len < sizeof(*unmap)) {
    1082           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1083           0 :                 return;
    1084             :         }
    1085             : 
    1086           0 :         unmap = (struct scsi_unmap_data *)xs->data;
    1087           0 :         if (_2btol(unmap->data_length) != len) {
    1088           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1089           0 :                 return;
    1090             :         }
    1091             : 
    1092           0 :         len = _2btol(unmap->desc_length);
    1093           0 :         if (len != xs->datalen - sizeof(*unmap)) {
    1094           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1095           0 :                 return;
    1096             :         }
    1097             : 
    1098           0 :         if (len < sizeof(struct scsi_unmap_desc)) {
    1099             :                 /* no work, no error according to sbc3 */
    1100           0 :                 atascsi_done(xs, XS_NOERROR);
    1101           0 :         }
    1102             : 
    1103           0 :         if (len > sizeof(struct scsi_unmap_desc) * 64) {
    1104             :                 /* more work than we advertised */
    1105           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1106           0 :                 return;
    1107             :         }
    1108             : 
    1109             :         /* let's go */
    1110           0 :         if (ISSET(xs->flags, SCSI_NOSLEEP)) {
    1111           0 :                 task_set(&xa->task, atascsi_disk_unmap_task, xs);
    1112           0 :                 task_add(systq, &xa->task);
    1113           0 :         } else {
    1114             :                 /* we can already sleep for memory */
    1115           0 :                 atascsi_disk_unmap_task(xs);
    1116             :         }
    1117           0 : }
    1118             : 
    1119             : void
    1120           0 : atascsi_disk_unmap_task(void *xxs)
    1121             : {
    1122           0 :         struct scsi_xfer        *xs = xxs;
    1123           0 :         struct scsi_link        *link = xs->sc_link;
    1124           0 :         struct atascsi          *as = link->adapter_softc;
    1125             :         struct atascsi_port     *ap;
    1126           0 :         struct ata_xfer         *xa = xs->io;
    1127             :         struct ata_fis_h2d      *fis;
    1128             :         struct scsi_unmap_data  *unmap;
    1129             :         struct scsi_unmap_desc  *descs, *d;
    1130             :         u_int64_t               *trims;
    1131             :         u_int                   len, i;
    1132             : 
    1133           0 :         trims = dma_alloc(512, PR_WAITOK | PR_ZERO);
    1134             : 
    1135           0 :         ap = atascsi_lookup_port(link);
    1136           0 :         unmap = (struct scsi_unmap_data *)xs->data;
    1137           0 :         descs = (struct scsi_unmap_desc *)(unmap + 1);
    1138             : 
    1139           0 :         len = _2btol(unmap->desc_length) / sizeof(*d);
    1140           0 :         for (i = 0; i < len; i++) {
    1141           0 :                 d = &descs[i];
    1142           0 :                 if (_4btol(d->logical_blocks) > ATA_DSM_TRIM_MAX_LEN)
    1143             :                         goto fail;
    1144             : 
    1145           0 :                 trims[i] = htole64(ATA_DSM_TRIM_DESC(_8btol(d->logical_addr),
    1146             :                     _4btol(d->logical_blocks)));
    1147             :         }
    1148             : 
    1149           0 :         xa->data = trims;
    1150           0 :         xa->datalen = 512;
    1151           0 :         xa->flags = ATA_F_WRITE;
    1152           0 :         xa->pmp_port = ap->ap_pmp_port;
    1153           0 :         xa->complete = atascsi_disk_unmap_done;
    1154           0 :         xa->atascsi_private = xs;
    1155           0 :         xa->timeout = (xs->timeout < 45000) ? 45000 : xs->timeout;
    1156             : 
    1157           0 :         fis = xa->fis;
    1158           0 :         fis->flags = ATA_H2D_FLAGS_CMD | ap->ap_pmp_port;
    1159           0 :         fis->command = ATA_C_DSM;
    1160           0 :         fis->features = ATA_DSM_TRIM;
    1161           0 :         fis->sector_count = 1;
    1162             : 
    1163           0 :         ata_exec(as, xa);
    1164           0 :         return;
    1165             : 
    1166             :  fail:
    1167           0 :         dma_free(xa->data, 512);
    1168           0 :         atascsi_done(xs, XS_DRIVER_STUFFUP);
    1169           0 : }
    1170             : 
    1171             : void
    1172           0 : atascsi_disk_unmap_done(struct ata_xfer *xa)
    1173             : {
    1174           0 :         struct scsi_xfer        *xs = xa->atascsi_private;
    1175             : 
    1176           0 :         dma_free(xa->data, 512);
    1177             : 
    1178           0 :         switch (xa->state) {
    1179             :         case ATA_S_COMPLETE:
    1180           0 :                 xs->error = XS_NOERROR;
    1181           0 :                 break;
    1182             :         case ATA_S_ERROR:
    1183           0 :                 xs->error = XS_DRIVER_STUFFUP;
    1184           0 :                 break;
    1185             :         case ATA_S_TIMEOUT:
    1186           0 :                 xs->error = XS_TIMEOUT;
    1187           0 :                 break;
    1188             : 
    1189             :         default:
    1190           0 :                 panic("atascsi_disk_unmap_done: "
    1191           0 :                     "unexpected ata_xfer state (%d)", xa->state);
    1192             :         }
    1193             : 
    1194           0 :         scsi_done(xs);
    1195           0 : }
    1196             : 
    1197             : void
    1198           0 : atascsi_disk_sync(struct scsi_xfer *xs)
    1199             : {
    1200           0 :         struct scsi_link        *link = xs->sc_link;
    1201           0 :         struct atascsi          *as = link->adapter_softc;
    1202             :         struct atascsi_port     *ap;
    1203           0 :         struct ata_xfer         *xa = xs->io;
    1204             : 
    1205           0 :         if (xs->cmdlen != sizeof(struct scsi_synchronize_cache)) {
    1206           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1207           0 :                 return;
    1208             :         }
    1209             : 
    1210           0 :         ap = atascsi_lookup_port(link);
    1211           0 :         xa->datalen = 0;
    1212           0 :         xa->flags = ATA_F_READ;
    1213           0 :         xa->complete = atascsi_disk_sync_done;
    1214             :         /* Spec says flush cache can take >30 sec, so give it at least 45. */
    1215           0 :         xa->timeout = (xs->timeout < 45000) ? 45000 : xs->timeout;
    1216           0 :         xa->atascsi_private = xs;
    1217           0 :         xa->pmp_port = ap->ap_pmp_port;
    1218           0 :         if (xs->flags & SCSI_POLL)
    1219           0 :                 xa->flags |= ATA_F_POLL;
    1220             : 
    1221           0 :         xa->fis->flags = ATA_H2D_FLAGS_CMD | ap->ap_pmp_port;
    1222           0 :         xa->fis->command = ATA_C_FLUSH_CACHE;
    1223           0 :         xa->fis->device = 0;
    1224             : 
    1225           0 :         ata_exec(as, xa);
    1226           0 : }
    1227             : 
    1228             : void
    1229           0 : atascsi_disk_sync_done(struct ata_xfer *xa)
    1230             : {
    1231           0 :         struct scsi_xfer        *xs = xa->atascsi_private;
    1232             : 
    1233           0 :         switch (xa->state) {
    1234             :         case ATA_S_COMPLETE:
    1235           0 :                 xs->error = XS_NOERROR;
    1236           0 :                 break;
    1237             : 
    1238             :         case ATA_S_ERROR:
    1239             :         case ATA_S_TIMEOUT:
    1240           0 :                 printf("atascsi_disk_sync_done: %s\n",
    1241           0 :                     xa->state == ATA_S_TIMEOUT ? "timeout" : "error");
    1242           0 :                 xs->error = (xa->state == ATA_S_TIMEOUT ? XS_TIMEOUT :
    1243             :                     XS_DRIVER_STUFFUP);
    1244           0 :                 break;
    1245             : 
    1246             :         default:
    1247           0 :                 panic("atascsi_disk_sync_done: unexpected ata_xfer state (%d)",
    1248           0 :                     xa->state);
    1249             :         }
    1250             : 
    1251           0 :         scsi_done(xs);
    1252           0 : }
    1253             : 
    1254             : u_int64_t
    1255           0 : ata_identify_blocks(struct ata_identify *id)
    1256             : {
    1257             :         u_int64_t               blocks = 0;
    1258             :         int                     i;
    1259             : 
    1260           0 :         if (letoh16(id->cmdset83) & 0x0400) {
    1261             :                 /* LBA48 feature set supported */
    1262           0 :                 for (i = 3; i >= 0; --i) {
    1263           0 :                         blocks <<= 16;
    1264           0 :                         blocks += letoh16(id->addrsecxt[i]);
    1265             :                 }
    1266             :         } else {
    1267           0 :                 blocks = letoh16(id->addrsec[1]);
    1268           0 :                 blocks <<= 16;
    1269           0 :                 blocks += letoh16(id->addrsec[0]);
    1270             :         }
    1271             : 
    1272           0 :         return (blocks - 1);
    1273             : }
    1274             : 
    1275             : u_int
    1276           0 : ata_identify_blocksize(struct ata_identify *id)
    1277             : {
    1278             :         u_int                   blocksize = 512;
    1279           0 :         u_int16_t               p2l_sect = letoh16(id->p2l_sect);
    1280             :         
    1281           0 :         if ((p2l_sect & ATA_ID_P2L_SECT_MASK) == ATA_ID_P2L_SECT_VALID &&
    1282           0 :             ISSET(p2l_sect, ATA_ID_P2L_SECT_SIZESET)) {
    1283           0 :                 blocksize = letoh16(id->words_lsec[1]);
    1284           0 :                 blocksize <<= 16;
    1285           0 :                 blocksize += letoh16(id->words_lsec[0]);
    1286           0 :                 blocksize <<= 1;
    1287           0 :         }
    1288             : 
    1289           0 :         return (blocksize);
    1290             : }
    1291             : 
    1292             : u_int
    1293           0 : ata_identify_block_l2p_exp(struct ata_identify *id)
    1294             : {
    1295             :         u_int                   exponent = 0;
    1296           0 :         u_int16_t               p2l_sect = letoh16(id->p2l_sect);
    1297             :         
    1298           0 :         if ((p2l_sect & ATA_ID_P2L_SECT_MASK) == ATA_ID_P2L_SECT_VALID &&
    1299           0 :             ISSET(p2l_sect, ATA_ID_P2L_SECT_SET)) {
    1300           0 :                 exponent = (p2l_sect & ATA_ID_P2L_SECT_SIZE);
    1301           0 :         }
    1302             : 
    1303           0 :         return (exponent);
    1304             : }
    1305             : 
    1306             : u_int
    1307           0 : ata_identify_block_logical_align(struct ata_identify *id)
    1308             : {
    1309             :         u_int                   align = 0;
    1310           0 :         u_int16_t               p2l_sect = letoh16(id->p2l_sect);
    1311           0 :         u_int16_t               logical_align = letoh16(id->logical_align);
    1312             :         
    1313           0 :         if ((p2l_sect & ATA_ID_P2L_SECT_MASK) == ATA_ID_P2L_SECT_VALID &&
    1314           0 :             ISSET(p2l_sect, ATA_ID_P2L_SECT_SET) &&
    1315           0 :             (logical_align & ATA_ID_LALIGN_MASK) == ATA_ID_LALIGN_VALID)
    1316           0 :                 align = logical_align & ATA_ID_LALIGN;
    1317             : 
    1318           0 :         return (align);
    1319             : }
    1320             : 
    1321             : void
    1322           0 : atascsi_disk_capacity(struct scsi_xfer *xs)
    1323             : {
    1324           0 :         struct scsi_link        *link = xs->sc_link;
    1325             :         struct atascsi_port     *ap;
    1326           0 :         struct scsi_read_cap_data rcd;
    1327             :         u_int64_t               capacity;
    1328             : 
    1329           0 :         ap = atascsi_lookup_port(link);
    1330           0 :         if (xs->cmdlen != sizeof(struct scsi_read_capacity)) {
    1331           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1332           0 :                 return;
    1333             :         }
    1334             : 
    1335           0 :         bzero(&rcd, sizeof(rcd));
    1336           0 :         capacity = ata_identify_blocks(&ap->ap_identify);
    1337           0 :         if (capacity > 0xffffffff)
    1338             :                 capacity = 0xffffffff;
    1339             : 
    1340           0 :         _lto4b(capacity, rcd.addr);
    1341           0 :         _lto4b(ata_identify_blocksize(&ap->ap_identify), rcd.length);
    1342             : 
    1343           0 :         bcopy(&rcd, xs->data, MIN(sizeof(rcd), xs->datalen));
    1344             : 
    1345           0 :         atascsi_done(xs, XS_NOERROR);
    1346           0 : }
    1347             : 
    1348             : void
    1349           0 : atascsi_disk_capacity16(struct scsi_xfer *xs)
    1350             : {
    1351           0 :         struct scsi_link        *link = xs->sc_link;
    1352             :         struct atascsi_port     *ap;
    1353           0 :         struct scsi_read_cap_data_16 rcd;
    1354             :         u_int                   align;
    1355             :         u_int16_t               lowest_aligned = 0;
    1356             : 
    1357           0 :         ap = atascsi_lookup_port(link);
    1358           0 :         if (xs->cmdlen != sizeof(struct scsi_read_capacity_16)) {
    1359           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1360           0 :                 return;
    1361             :         }
    1362             : 
    1363           0 :         bzero(&rcd, sizeof(rcd));
    1364             : 
    1365           0 :         _lto8b(ata_identify_blocks(&ap->ap_identify), rcd.addr);
    1366           0 :         _lto4b(ata_identify_blocksize(&ap->ap_identify), rcd.length);
    1367           0 :         rcd.logical_per_phys = ata_identify_block_l2p_exp(&ap->ap_identify);
    1368           0 :         align = ata_identify_block_logical_align(&ap->ap_identify);
    1369           0 :         if (align > 0)
    1370           0 :                 lowest_aligned = (1 << rcd.logical_per_phys) - align;
    1371             : 
    1372           0 :         if (ISSET(ap->ap_features, ATA_PORT_F_TRIM)) {
    1373           0 :                 SET(lowest_aligned, READ_CAP_16_TPE);
    1374             : 
    1375           0 :                 if (ISSET(letoh16(ap->ap_identify.add_support), 
    1376             :                     ATA_ID_ADD_SUPPORT_DRT))
    1377           0 :                         SET(lowest_aligned, READ_CAP_16_TPRZ);
    1378             :         }
    1379           0 :         _lto2b(lowest_aligned, rcd.lowest_aligned);
    1380             : 
    1381           0 :         bcopy(&rcd, xs->data, MIN(sizeof(rcd), xs->datalen));
    1382             : 
    1383           0 :         atascsi_done(xs, XS_NOERROR);
    1384           0 : }
    1385             : 
    1386             : int
    1387           0 : atascsi_passthru_map(struct scsi_xfer *xs, u_int8_t count_proto, u_int8_t flags)
    1388             : {
    1389           0 :         struct ata_xfer         *xa = xs->io;
    1390             : 
    1391           0 :         xa->data = xs->data;
    1392           0 :         xa->datalen = xs->datalen;
    1393           0 :         xa->timeout = xs->timeout;
    1394           0 :         xa->flags = 0;
    1395           0 :         if (xs->flags & SCSI_DATA_IN)
    1396           0 :                 xa->flags |= ATA_F_READ;
    1397           0 :         if (xs->flags & SCSI_DATA_OUT)
    1398           0 :                 xa->flags |= ATA_F_WRITE;
    1399           0 :         if (xs->flags & SCSI_POLL)
    1400           0 :                 xa->flags |= ATA_F_POLL;
    1401             : 
    1402           0 :         switch (count_proto & ATA_PASSTHRU_PROTO_MASK) {
    1403             :         case ATA_PASSTHRU_PROTO_NON_DATA:
    1404             :         case ATA_PASSTHRU_PROTO_PIO_DATAIN:
    1405             :         case ATA_PASSTHRU_PROTO_PIO_DATAOUT:
    1406           0 :                 xa->flags |= ATA_F_PIO;
    1407             :                 break;
    1408             :         default:
    1409             :                 /* we dont support this yet */
    1410           0 :                 return (1);
    1411             :         }
    1412             : 
    1413           0 :         xa->atascsi_private = xs;
    1414           0 :         xa->complete = atascsi_passthru_done;
    1415             : 
    1416           0 :         return (0);
    1417           0 : }
    1418             : 
    1419             : void
    1420           0 : atascsi_passthru_12(struct scsi_xfer *xs)
    1421             : {
    1422           0 :         struct scsi_link        *link = xs->sc_link;
    1423           0 :         struct atascsi          *as = link->adapter_softc;
    1424             :         struct atascsi_port     *ap;
    1425           0 :         struct ata_xfer         *xa = xs->io;
    1426             :         struct scsi_ata_passthru_12 *cdb;
    1427             :         struct ata_fis_h2d      *fis;
    1428             : 
    1429           0 :         if (xs->cmdlen != sizeof(*cdb)) {
    1430           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1431           0 :                 return;
    1432             :         }
    1433             : 
    1434           0 :         cdb = (struct scsi_ata_passthru_12 *)xs->cmd;
    1435             :         /* validate cdb */
    1436             : 
    1437           0 :         if (atascsi_passthru_map(xs, cdb->count_proto, cdb->flags) != 0) {
    1438           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1439           0 :                 return;
    1440             :         }
    1441             : 
    1442           0 :         ap = atascsi_lookup_port(link);
    1443           0 :         fis = xa->fis;
    1444           0 :         fis->flags = ATA_H2D_FLAGS_CMD | ap->ap_pmp_port;
    1445           0 :         fis->command = cdb->command;
    1446           0 :         fis->features = cdb->features;
    1447           0 :         fis->lba_low = cdb->lba_low;
    1448           0 :         fis->lba_mid = cdb->lba_mid;
    1449           0 :         fis->lba_high = cdb->lba_high;
    1450           0 :         fis->device = cdb->device;
    1451           0 :         fis->sector_count = cdb->sector_count;
    1452           0 :         xa->pmp_port = ap->ap_pmp_port;
    1453             : 
    1454           0 :         ata_exec(as, xa);
    1455           0 : }
    1456             : 
    1457             : void
    1458           0 : atascsi_passthru_16(struct scsi_xfer *xs)
    1459             : {
    1460           0 :         struct scsi_link        *link = xs->sc_link;
    1461           0 :         struct atascsi          *as = link->adapter_softc;
    1462             :         struct atascsi_port     *ap;
    1463           0 :         struct ata_xfer         *xa = xs->io;
    1464             :         struct scsi_ata_passthru_16 *cdb;
    1465             :         struct ata_fis_h2d      *fis;
    1466             : 
    1467           0 :         if (xs->cmdlen != sizeof(*cdb)) {
    1468           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1469           0 :                 return;
    1470             :         }
    1471             : 
    1472           0 :         cdb = (struct scsi_ata_passthru_16 *)xs->cmd;
    1473             :         /* validate cdb */
    1474             : 
    1475           0 :         if (atascsi_passthru_map(xs, cdb->count_proto, cdb->flags) != 0) {
    1476           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1477           0 :                 return;
    1478             :         }
    1479             : 
    1480           0 :         ap = atascsi_lookup_port(link);
    1481           0 :         fis = xa->fis;
    1482           0 :         fis->flags = ATA_H2D_FLAGS_CMD | ap->ap_pmp_port;
    1483           0 :         fis->command = cdb->command;
    1484           0 :         fis->features = cdb->features[1];
    1485           0 :         fis->lba_low = cdb->lba_low[1];
    1486           0 :         fis->lba_mid = cdb->lba_mid[1];
    1487           0 :         fis->lba_high = cdb->lba_high[1];
    1488           0 :         fis->device = cdb->device;
    1489           0 :         fis->lba_low_exp = cdb->lba_low[0];
    1490           0 :         fis->lba_mid_exp = cdb->lba_mid[0];
    1491           0 :         fis->lba_high_exp = cdb->lba_high[0];
    1492           0 :         fis->features_exp = cdb->features[0];
    1493           0 :         fis->sector_count = cdb->sector_count[1];
    1494           0 :         fis->sector_count_exp = cdb->sector_count[0];
    1495           0 :         xa->pmp_port = ap->ap_pmp_port;
    1496             : 
    1497           0 :         ata_exec(as, xa);
    1498           0 : }
    1499             : 
    1500             : void
    1501           0 : atascsi_passthru_done(struct ata_xfer *xa)
    1502             : {
    1503           0 :         struct scsi_xfer        *xs = xa->atascsi_private;
    1504             : 
    1505             :         /*
    1506             :          * XXX need to generate sense if cdb wants it
    1507             :          */
    1508             : 
    1509           0 :         switch (xa->state) {
    1510             :         case ATA_S_COMPLETE:
    1511           0 :                 xs->error = XS_NOERROR;
    1512           0 :                 break;
    1513             :         case ATA_S_ERROR:
    1514           0 :                 xs->error = XS_DRIVER_STUFFUP;
    1515           0 :                 break;
    1516             :         case ATA_S_TIMEOUT:
    1517           0 :                 printf("atascsi_passthru_done, timeout\n");
    1518           0 :                 xs->error = XS_TIMEOUT;
    1519           0 :                 break;
    1520             :         default:
    1521           0 :                 panic("atascsi_atapi_cmd_done: unexpected ata_xfer state (%d)",
    1522           0 :                     xa->state);
    1523             :         }
    1524             : 
    1525           0 :         xs->resid = xa->resid;
    1526             : 
    1527           0 :         scsi_done(xs);
    1528           0 : }
    1529             : 
    1530             : void
    1531           0 : atascsi_disk_sense(struct scsi_xfer *xs)
    1532             : {
    1533           0 :         struct scsi_sense_data  *sd = (struct scsi_sense_data *)xs->data;
    1534             : 
    1535           0 :         bzero(xs->data, xs->datalen);
    1536             :         /* check datalen > sizeof(struct scsi_sense_data)? */
    1537           0 :         sd->error_code = SSD_ERRCODE_CURRENT;
    1538           0 :         sd->flags = SKEY_NO_SENSE;
    1539             : 
    1540           0 :         atascsi_done(xs, XS_NOERROR);
    1541           0 : }
    1542             : 
    1543             : void
    1544           0 : atascsi_disk_start_stop(struct scsi_xfer *xs)
    1545             : {
    1546           0 :         struct scsi_link        *link = xs->sc_link;
    1547           0 :         struct atascsi          *as = link->adapter_softc;
    1548             :         struct atascsi_port     *ap;
    1549           0 :         struct ata_xfer         *xa = xs->io;
    1550           0 :         struct scsi_start_stop  *ss = (struct scsi_start_stop *)xs->cmd;
    1551             : 
    1552           0 :         if (xs->cmdlen != sizeof(*ss)) {
    1553           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1554           0 :                 return;
    1555             :         }
    1556             : 
    1557           0 :         if (ss->how != SSS_STOP) {
    1558           0 :                 atascsi_done(xs, XS_NOERROR);
    1559           0 :                 return;
    1560             :         }
    1561             : 
    1562             :         /*
    1563             :          * A SCSI START STOP UNIT command with the START bit set to
    1564             :          * zero gets translated into an ATA FLUSH CACHE command
    1565             :          * followed by an ATA STANDBY IMMEDIATE command.
    1566             :          */
    1567           0 :         ap = atascsi_lookup_port(link);
    1568           0 :         xa->datalen = 0;
    1569           0 :         xa->flags = ATA_F_READ;
    1570           0 :         xa->complete = atascsi_disk_start_stop_done;
    1571             :         /* Spec says flush cache can take >30 sec, so give it at least 45. */
    1572           0 :         xa->timeout = (xs->timeout < 45000) ? 45000 : xs->timeout;
    1573           0 :         xa->pmp_port = ap->ap_pmp_port;
    1574           0 :         xa->atascsi_private = xs;
    1575           0 :         if (xs->flags & SCSI_POLL)
    1576           0 :                 xa->flags |= ATA_F_POLL;
    1577             : 
    1578           0 :         xa->fis->flags = ATA_H2D_FLAGS_CMD | ap->ap_pmp_port;
    1579           0 :         xa->fis->command = ATA_C_FLUSH_CACHE;
    1580           0 :         xa->fis->device = 0;
    1581             : 
    1582           0 :         ata_exec(as, xa);
    1583           0 : }
    1584             : 
    1585             : void
    1586           0 : atascsi_disk_start_stop_done(struct ata_xfer *xa)
    1587             : {
    1588           0 :         struct scsi_xfer        *xs = xa->atascsi_private;
    1589           0 :         struct scsi_link        *link = xs->sc_link;
    1590           0 :         struct atascsi          *as = link->adapter_softc;
    1591             :         struct atascsi_port     *ap;
    1592             : 
    1593           0 :         switch (xa->state) {
    1594             :         case ATA_S_COMPLETE:
    1595             :                 break;
    1596             : 
    1597             :         case ATA_S_ERROR:
    1598             :         case ATA_S_TIMEOUT:
    1599           0 :                 xs->error = (xa->state == ATA_S_TIMEOUT ? XS_TIMEOUT :
    1600             :                     XS_DRIVER_STUFFUP);
    1601           0 :                 xs->resid = xa->resid;
    1602           0 :                 scsi_done(xs);
    1603           0 :                 return;
    1604             : 
    1605             :         default:
    1606           0 :                 panic("atascsi_disk_start_stop_done: unexpected ata_xfer state (%d)",
    1607           0 :                     xa->state);
    1608             :         }
    1609             : 
    1610             :         /*
    1611             :          * The FLUSH CACHE command completed succesfully; now issue
    1612             :          * the STANDBY IMMEDATE command.
    1613             :          */
    1614           0 :         ap = atascsi_lookup_port(link);
    1615           0 :         xa->datalen = 0;
    1616           0 :         xa->flags = ATA_F_READ;
    1617           0 :         xa->state = ATA_S_SETUP;
    1618           0 :         xa->complete = atascsi_disk_cmd_done;
    1619             :         /* Spec says flush cache can take >30 sec, so give it at least 45. */
    1620           0 :         xa->timeout = (xs->timeout < 45000) ? 45000 : xs->timeout;
    1621           0 :         xa->pmp_port = ap->ap_pmp_port;
    1622           0 :         xa->atascsi_private = xs;
    1623           0 :         if (xs->flags & SCSI_POLL)
    1624           0 :                 xa->flags |= ATA_F_POLL;
    1625             : 
    1626           0 :         xa->fis->flags = ATA_H2D_FLAGS_CMD | ap->ap_pmp_port;
    1627           0 :         xa->fis->command = ATA_C_STANDBY_IMMED;
    1628           0 :         xa->fis->device = 0;
    1629             : 
    1630           0 :         ata_exec(as, xa);
    1631           0 : }
    1632             : 
    1633             : void
    1634           0 : atascsi_atapi_cmd(struct scsi_xfer *xs)
    1635             : {
    1636           0 :         struct scsi_link        *link = xs->sc_link;
    1637           0 :         struct atascsi          *as = link->adapter_softc;
    1638             :         struct atascsi_port     *ap;
    1639           0 :         struct ata_xfer         *xa = xs->io;
    1640             :         struct ata_fis_h2d      *fis;
    1641             : 
    1642           0 :         switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
    1643             :         case SCSI_DATA_IN:
    1644           0 :                 xa->flags = ATA_F_PACKET | ATA_F_READ;
    1645           0 :                 break;
    1646             :         case SCSI_DATA_OUT:
    1647           0 :                 xa->flags = ATA_F_PACKET | ATA_F_WRITE;
    1648           0 :                 break;
    1649             :         default:
    1650           0 :                 xa->flags = ATA_F_PACKET;
    1651           0 :         }
    1652           0 :         xa->flags |= ATA_F_GET_RFIS;
    1653             : 
    1654           0 :         ap = atascsi_lookup_port(link);
    1655           0 :         xa->data = xs->data;
    1656           0 :         xa->datalen = xs->datalen;
    1657           0 :         xa->complete = atascsi_atapi_cmd_done;
    1658           0 :         xa->timeout = xs->timeout;
    1659           0 :         xa->pmp_port = ap->ap_pmp_port;
    1660           0 :         xa->atascsi_private = xs;
    1661           0 :         if (xs->flags & SCSI_POLL)
    1662           0 :                 xa->flags |= ATA_F_POLL;
    1663             : 
    1664           0 :         fis = xa->fis;
    1665           0 :         fis->flags = ATA_H2D_FLAGS_CMD | ap->ap_pmp_port;
    1666           0 :         fis->command = ATA_C_PACKET;
    1667           0 :         fis->device = 0;
    1668           0 :         fis->sector_count = xa->tag << 3;
    1669           0 :         fis->features = ATA_H2D_FEATURES_DMA | ((xa->flags & ATA_F_WRITE) ?
    1670             :             ATA_H2D_FEATURES_DIR_WRITE : ATA_H2D_FEATURES_DIR_READ);
    1671           0 :         fis->lba_mid = 0x00;
    1672           0 :         fis->lba_high = 0x20;
    1673             : 
    1674             :         /* Copy SCSI command into ATAPI packet. */
    1675           0 :         memcpy(xa->packetcmd, xs->cmd, xs->cmdlen);
    1676             : 
    1677           0 :         ata_exec(as, xa);
    1678           0 : }
    1679             : 
    1680             : void
    1681           0 : atascsi_atapi_cmd_done(struct ata_xfer *xa)
    1682             : {
    1683           0 :         struct scsi_xfer        *xs = xa->atascsi_private;
    1684           0 :         struct scsi_sense_data  *sd = &xs->sense;
    1685             : 
    1686           0 :         switch (xa->state) {
    1687             :         case ATA_S_COMPLETE:
    1688           0 :                 xs->error = XS_NOERROR;
    1689           0 :                 break;
    1690             :         case ATA_S_ERROR:
    1691             :                 /* Return PACKET sense data */
    1692           0 :                 sd->error_code = SSD_ERRCODE_CURRENT;
    1693           0 :                 sd->flags = (xa->rfis.error & 0xf0) >> 4;
    1694           0 :                 if (xa->rfis.error & 0x04)
    1695           0 :                         sd->flags = SKEY_ILLEGAL_REQUEST;
    1696           0 :                 if (xa->rfis.error & 0x02)
    1697           0 :                         sd->flags |= SSD_EOM;
    1698           0 :                 if (xa->rfis.error & 0x01)
    1699           0 :                         sd->flags |= SSD_ILI;
    1700           0 :                 xs->error = XS_SENSE;
    1701           0 :                 break;
    1702             :         case ATA_S_TIMEOUT:
    1703           0 :                 printf("atascsi_atapi_cmd_done, timeout\n");
    1704           0 :                 xs->error = XS_TIMEOUT;
    1705           0 :                 break;
    1706             :         default:
    1707           0 :                 panic("atascsi_atapi_cmd_done: unexpected ata_xfer state (%d)",
    1708           0 :                     xa->state);
    1709             :         }
    1710             : 
    1711           0 :         xs->resid = xa->resid;
    1712             : 
    1713           0 :         scsi_done(xs);
    1714           0 : }
    1715             : 
    1716             : void
    1717           0 : atascsi_pmp_cmd(struct scsi_xfer *xs)
    1718             : {
    1719           0 :         switch (xs->cmd->opcode) {
    1720             :         case REQUEST_SENSE:
    1721           0 :                 atascsi_pmp_sense(xs);
    1722           0 :                 return;
    1723             :         case INQUIRY:
    1724           0 :                 atascsi_pmp_inq(xs);
    1725           0 :                 return;
    1726             : 
    1727             :         case TEST_UNIT_READY:
    1728             :         case PREVENT_ALLOW:
    1729           0 :                 atascsi_done(xs, XS_NOERROR);
    1730           0 :                 return;
    1731             : 
    1732             :         default:
    1733           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1734           0 :                 return;
    1735             :         }
    1736           0 : }
    1737             : 
    1738             : void
    1739           0 : atascsi_pmp_sense(struct scsi_xfer *xs)
    1740             : {
    1741           0 :         struct scsi_sense_data *sd = (struct scsi_sense_data *)xs->data;
    1742             : 
    1743           0 :         bzero(xs->data, xs->datalen);
    1744           0 :         sd->error_code = SSD_ERRCODE_CURRENT;
    1745           0 :         sd->flags = SKEY_NO_SENSE;
    1746             : 
    1747           0 :         atascsi_done(xs, XS_NOERROR);
    1748           0 : }
    1749             : 
    1750             : void
    1751           0 : atascsi_pmp_inq(struct scsi_xfer *xs)
    1752             : {
    1753           0 :         struct scsi_inquiry_data inq;
    1754           0 :         struct scsi_inquiry *in_inq = (struct scsi_inquiry *)xs->cmd;
    1755             : 
    1756           0 :         if (ISSET(in_inq->flags, SI_EVPD)) {
    1757             :                 /* any evpd pages we need to support here? */
    1758           0 :                 atascsi_done(xs, XS_DRIVER_STUFFUP);
    1759           0 :                 return;
    1760             :         }
    1761             : 
    1762           0 :         bzero(&inq, sizeof(inq));
    1763           0 :         inq.device = 0x1E;      /* "well known logical unit" seems reasonable */
    1764           0 :         inq.version = 0x05;     /* SPC-3? */
    1765           0 :         inq.response_format = 2;
    1766           0 :         inq.additional_length = 32;
    1767           0 :         inq.flags |= SID_CmdQue;
    1768           0 :         bcopy("ATA     ", inq.vendor, sizeof(inq.vendor));
    1769             : 
    1770             :         /* should use the data from atascsi_pmp_identify here?
    1771             :          * not sure how useful the chip id is, but maybe it'd be
    1772             :          * nice to include the number of ports.
    1773             :          */
    1774           0 :         bcopy("Port Multiplier", inq.product, sizeof(inq.product));
    1775           0 :         bcopy("    ", inq.revision, sizeof(inq.revision));
    1776             : 
    1777           0 :         bcopy(&inq, xs->data, MIN(sizeof(inq), xs->datalen));
    1778           0 :         atascsi_done(xs, XS_NOERROR);
    1779           0 : }
    1780             : 
    1781             : void
    1782           0 : atascsi_done(struct scsi_xfer *xs, int error)
    1783             : {
    1784           0 :         xs->error = error;
    1785           0 :         scsi_done(xs);
    1786           0 : }
    1787             : 
    1788             : void
    1789           0 : ata_exec(struct atascsi *as, struct ata_xfer *xa)
    1790             : {
    1791           0 :         as->as_methods->ata_cmd(xa);
    1792           0 : }
    1793             : 
    1794             : void *
    1795           0 : atascsi_io_get(void *cookie)
    1796             : {
    1797           0 :         struct atascsi_host_port        *ahp = cookie;
    1798           0 :         struct atascsi                  *as = ahp->ahp_as;
    1799             :         struct ata_xfer                 *xa;
    1800             : 
    1801           0 :         xa = as->as_methods->ata_get_xfer(as->as_cookie, ahp->ahp_port);
    1802           0 :         if (xa != NULL)
    1803           0 :                 xa->fis->type = ATA_FIS_TYPE_H2D;
    1804             : 
    1805           0 :         return (xa);
    1806             : }
    1807             : 
    1808             : void
    1809           0 : atascsi_io_put(void *cookie, void *io)
    1810             : {
    1811           0 :         struct atascsi_host_port        *ahp = cookie;
    1812           0 :         struct atascsi                  *as = ahp->ahp_as;
    1813           0 :         struct ata_xfer                 *xa = io;
    1814             : 
    1815           0 :         xa->state = ATA_S_COMPLETE; /* XXX this state machine is dumb */
    1816           0 :         as->as_methods->ata_put_xfer(xa);
    1817           0 : }
    1818             : 
    1819             : void
    1820           0 : ata_polled_complete(struct ata_xfer *xa)
    1821             : {
    1822             :         /* do nothing */
    1823           0 : }
    1824             : 
    1825             : int
    1826           0 : ata_polled(struct ata_xfer *xa)
    1827             : {
    1828             :         int                     rv;
    1829             : 
    1830           0 :         if (!ISSET(xa->flags, ATA_F_DONE))
    1831           0 :                 panic("ata_polled: xa isnt complete");
    1832             : 
    1833           0 :         switch (xa->state) {
    1834             :         case ATA_S_COMPLETE:
    1835             :                 rv = 0;
    1836           0 :                 break;
    1837             :         case ATA_S_ERROR:
    1838             :         case ATA_S_TIMEOUT:
    1839             :                 rv = EIO;
    1840           0 :                 break;
    1841             :         default:
    1842           0 :                 panic("ata_polled: xa state (%d)",
    1843           0 :                     xa->state);
    1844             :         }
    1845             : 
    1846           0 :         scsi_io_put(xa->atascsi_private, xa);
    1847             : 
    1848           0 :         return (rv);
    1849             : }
    1850             : 
    1851             : void
    1852           0 : ata_complete(struct ata_xfer *xa)
    1853             : {
    1854           0 :         SET(xa->flags, ATA_F_DONE);
    1855           0 :         xa->complete(xa);
    1856           0 : }
    1857             : 
    1858             : void
    1859           0 : ata_swapcopy(void *src, void *dst, size_t len)
    1860             : {
    1861           0 :         u_int16_t *s = src, *d = dst;
    1862             :         int i;
    1863             : 
    1864           0 :         len /= 2;
    1865             : 
    1866           0 :         for (i = 0; i < len; i++)
    1867           0 :                 d[i] = swap16(s[i]);
    1868           0 : }
    1869             : 
    1870             : int
    1871           0 : atascsi_port_identify(struct atascsi_port *ap, struct ata_identify *identify)
    1872             : {
    1873           0 :         struct atascsi                  *as = ap->ap_as;
    1874           0 :         struct atascsi_host_port        *ahp = ap->ap_host_port;
    1875             :         struct ata_xfer                 *xa;
    1876             : 
    1877           0 :         xa = scsi_io_get(&ahp->ahp_iopool, SCSI_NOSLEEP);
    1878           0 :         if (xa == NULL)
    1879           0 :                 panic("no free xfers on a new port");
    1880           0 :         xa->pmp_port = ap->ap_pmp_port;
    1881           0 :         xa->data = identify;
    1882           0 :         xa->datalen = sizeof(*identify);
    1883           0 :         xa->fis->flags = ATA_H2D_FLAGS_CMD | ap->ap_pmp_port;
    1884           0 :         xa->fis->command = (ap->ap_type == ATA_PORT_T_DISK) ?
    1885             :             ATA_C_IDENTIFY : ATA_C_IDENTIFY_PACKET;
    1886           0 :         xa->fis->device = 0;
    1887           0 :         xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
    1888           0 :         xa->timeout = 1000;
    1889           0 :         xa->complete = ata_polled_complete;
    1890           0 :         xa->atascsi_private = &ahp->ahp_iopool;
    1891           0 :         ata_exec(as, xa);
    1892           0 :         return (ata_polled(xa));
    1893             : }
    1894             : 
    1895             : int
    1896           0 : atascsi_port_set_features(struct atascsi_port *ap, int subcommand, int arg)
    1897             : {
    1898           0 :         struct atascsi                  *as = ap->ap_as;
    1899           0 :         struct atascsi_host_port        *ahp = ap->ap_host_port;
    1900             :         struct ata_xfer                 *xa;
    1901             : 
    1902           0 :         xa = scsi_io_get(&ahp->ahp_iopool, SCSI_NOSLEEP);
    1903           0 :         if (xa == NULL)
    1904           0 :                 panic("no free xfers on a new port");
    1905           0 :         xa->fis->command = ATA_C_SET_FEATURES;
    1906           0 :         xa->fis->features = subcommand;
    1907           0 :         xa->fis->sector_count = arg;
    1908           0 :         xa->fis->flags = ATA_H2D_FLAGS_CMD | ap->ap_pmp_port;
    1909           0 :         xa->flags = ATA_F_POLL;
    1910           0 :         xa->timeout = 1000;
    1911           0 :         xa->complete = ata_polled_complete;
    1912           0 :         xa->pmp_port = ap->ap_pmp_port;
    1913           0 :         xa->atascsi_private = &ahp->ahp_iopool;
    1914           0 :         ata_exec(as, xa);
    1915           0 :         return (ata_polled(xa));
    1916             : }

Generated by: LCOV version 1.13