SILI - Work around hardware LRAM bugs part 2/2.
[dragonfly.git] / sys / dev / disk / sili / sili_cam.c
1 /*
2  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *
35  * Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
36  *
37  * Permission to use, copy, modify, and distribute this software for any
38  * purpose with or without fee is hereby granted, provided that the above
39  * copyright notice and this permission notice appear in all copies.
40  *
41  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
42  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
43  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
44  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
45  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
46  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
47  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
48  *
49  * $OpenBSD: atascsi.c,v 1.64 2009/02/16 21:19:06 miod Exp $
50  * $DragonFly$
51  */
52 /*
53  * Implement each SATA port as its own SCSI bus on CAM.  This way we can
54  * implement future port multiplier features as individual devices on the
55  * bus.
56  *
57  * Much of the cdb<->xa conversion code was taken from OpenBSD, the rest
58  * was written natively for DragonFly.
59  */
60
61 #include "sili.h"
62
63 const char *ScsiTypeArray[32] = {
64         "DIRECT",
65         "SEQUENTIAL",
66         "PRINTER",
67         "PROCESSOR",
68         "WORM",
69         "CDROM",
70         "SCANNER",
71         "OPTICAL",
72         "CHANGER",
73         "COMM",
74         "ASC0",
75         "ASC1",
76         "STORARRAY",
77         "ENCLOSURE",
78         "RBC",
79         "OCRW",
80         "0x10",
81         "OSD",
82         "ADC",
83         "0x13",
84         "0x14",
85         "0x15",
86         "0x16",
87         "0x17",
88         "0x18",
89         "0x19",
90         "0x1A",
91         "0x1B",
92         "0x1C",
93         "0x1D",
94         "0x1E",
95         "NODEVICE"
96 };
97
98 static void sili_xpt_action(struct cam_sim *sim, union ccb *ccb);
99 static void sili_xpt_poll(struct cam_sim *sim);
100 static void sili_xpt_scsi_disk_io(struct sili_port *ap,
101                         struct ata_port *at, union ccb *ccb);
102 static void sili_xpt_scsi_atapi_io(struct sili_port *ap,
103                         struct ata_port *at, union ccb *ccb);
104
105 static void sili_ata_complete_disk_rw(struct ata_xfer *xa);
106 static void sili_ata_complete_disk_synchronize_cache(struct ata_xfer *xa);
107 static void sili_atapi_complete_cmd(struct ata_xfer *xa);
108 static void sili_ata_dummy_sense(struct scsi_sense_data *sense_data);
109 static void sili_ata_atapi_sense(struct ata_fis_d2h *rfis,
110                      struct scsi_sense_data *sense_data);
111
112 static int sili_cam_probe_disk(struct sili_port *ap, struct ata_port *at);
113 static int sili_cam_probe_atapi(struct sili_port *ap, struct ata_port *at);
114 static void sili_ata_dummy_done(struct ata_xfer *xa);
115 static void ata_fix_identify(struct ata_identify *id);
116 static void sili_cam_rescan(struct sili_port *ap);
117
118 int
119 sili_cam_attach(struct sili_port *ap)
120 {
121         struct cam_devq *devq;
122         struct cam_sim *sim;
123         int error;
124         int unit;
125
126         kprintf("%s: CAM ATTACH\n", PORTNAME(ap));
127         /*
128          * We want at least one ccb to be available for error processing
129          * so don't let CAM use more then ncmds - 1.
130          */
131         unit = device_get_unit(ap->ap_sc->sc_dev);
132         if (ap->ap_sc->sc_ncmds > 1)
133                 devq = cam_simq_alloc(ap->ap_sc->sc_ncmds - 1);
134         else
135                 devq = cam_simq_alloc(ap->ap_sc->sc_ncmds);
136         if (devq == NULL) {
137                 return (ENOMEM);
138         }
139         sim = cam_sim_alloc(sili_xpt_action, sili_xpt_poll, "sili",
140                            (void *)ap, unit, &sim_mplock, 1, 1, devq);
141         cam_simq_release(devq);
142         if (sim == NULL) {
143                 return (ENOMEM);
144         }
145         ap->ap_sim = sim;
146         sili_os_unlock_port(ap);
147         error = xpt_bus_register(ap->ap_sim, ap->ap_num);
148         sili_os_lock_port(ap);
149         if (error != CAM_SUCCESS) {
150                 sili_cam_detach(ap);
151                 return (EINVAL);
152         }
153         kprintf("%s: CAM ATTACH2\n", PORTNAME(ap));
154         ap->ap_flags |= AP_F_BUS_REGISTERED;
155         kprintf("%s: CAM ATTACH3 %d\n", PORTNAME(ap), ap->ap_probe);
156
157         if (ap->ap_probe == ATA_PROBE_NEED_IDENT)
158                 error = sili_cam_probe(ap, NULL);
159         else
160                 error = 0;
161         if (error) {
162                 sili_cam_detach(ap);
163                 return (EIO);
164         }
165         ap->ap_flags |= AP_F_CAM_ATTACHED;
166
167         return(0);
168 }
169
170 /*
171  * The state of the port has changed.
172  *
173  * If at is NULL the physical port has changed state.
174  * If at is non-NULL a particular target behind a PM has changed state.
175  *
176  * If found is -1 the target state must be queued to a non-interrupt context.
177  * (only works with at == NULL).
178  *
179  * If found is 0 the target was removed.
180  * If found is 1 the target was inserted.
181  */
182 void
183 sili_cam_changed(struct sili_port *ap, struct ata_port *atx, int found)
184 {
185         struct cam_path *tmppath;
186         int status;
187         int target;
188
189         target = atx ? atx->at_target : CAM_TARGET_WILDCARD;
190
191         if (ap->ap_sim == NULL)
192                 return;
193         if (found == CAM_TARGET_WILDCARD) {
194                 status = xpt_create_path(&tmppath, NULL,
195                                          cam_sim_path(ap->ap_sim),
196                                          target, CAM_LUN_WILDCARD);
197                 if (status != CAM_REQ_CMP)
198                         return;
199                 sili_cam_rescan(ap);
200         } else {
201                 status = xpt_create_path(&tmppath, NULL,
202                                          cam_sim_path(ap->ap_sim),
203                                          target,
204                                          CAM_LUN_WILDCARD);
205                 if (status != CAM_REQ_CMP)
206                         return;
207 #if 0
208                 /*
209                  * This confuses CAM
210                  */
211                 if (found)
212                         xpt_async(AC_FOUND_DEVICE, tmppath, NULL);
213                 else
214                         xpt_async(AC_LOST_DEVICE, tmppath, NULL);
215 #endif
216         }
217         xpt_free_path(tmppath);
218 }
219
220 void
221 sili_cam_detach(struct sili_port *ap)
222 {
223         int error;
224
225         if ((ap->ap_flags & AP_F_CAM_ATTACHED) == 0)
226                 return;
227         get_mplock();
228         if (ap->ap_sim) {
229                 xpt_freeze_simq(ap->ap_sim, 1);
230         }
231         if (ap->ap_flags & AP_F_BUS_REGISTERED) {
232                 error = xpt_bus_deregister(cam_sim_path(ap->ap_sim));
233                 KKASSERT(error == CAM_REQ_CMP);
234                 ap->ap_flags &= ~AP_F_BUS_REGISTERED;
235         }
236         if (ap->ap_sim) {
237                 cam_sim_free(ap->ap_sim);
238                 ap->ap_sim = NULL;
239         }
240         rel_mplock();
241         ap->ap_flags &= ~AP_F_CAM_ATTACHED;
242 }
243
244 /*
245  * Once the SILI port has been attached we need to probe for a device or
246  * devices on the port and setup various options.
247  *
248  * If at is NULL we are probing the direct-attached device on the port,
249  * which may or may not be a port multiplier.
250  */
251 int
252 sili_cam_probe(struct sili_port *ap, struct ata_port *atx)
253 {
254         struct ata_port *at;
255         struct ata_xfer *xa;
256         u_int64_t       capacity;
257         u_int64_t       capacity_bytes;
258         int             model_len;
259         int             error;
260         int             devncqdepth;
261         int             i;
262         const char      *wcstr;
263         const char      *rastr;
264         const char      *scstr;
265         const char      *type;
266
267         error = EIO;
268
269         /*
270          * Delayed CAM attachment for initial probe, sim may be NULL
271          */
272         if (ap->ap_sim == NULL)
273                 return(0);
274
275         /*
276          * A NULL atx indicates a probe of the directly connected device.
277          * A non-NULL atx indicates a device connected via a port multiplier.
278          * We need to preserve atx for calls to sili_ata_get_xfer().
279          *
280          * at is always non-NULL.  For directly connected devices we supply
281          * an (at) pointing to target 0.
282          */
283         if (atx == NULL) {
284                 at = ap->ap_ata;        /* direct attached - device 0 */
285                 if (ap->ap_type == ATA_PORT_T_PM) {
286                         kprintf("%s: Found Port Multiplier\n",
287                                 ATANAME(ap, atx));
288                         return (0);
289                 }
290                 at->at_type = ap->ap_type;
291         } else {
292                 at = atx;
293                 if (atx->at_type == ATA_PORT_T_PM) {
294                         kprintf("%s: Bogus device, reducing port count to %d\n",
295                                 ATANAME(ap, atx), atx->at_target);
296                         if (ap->ap_pmcount > atx->at_target)
297                                 ap->ap_pmcount = atx->at_target;
298                         goto err;
299                 }
300         }
301         if (ap->ap_type == ATA_PORT_T_NONE)
302                 goto err;
303         if (at->at_type == ATA_PORT_T_NONE)
304                 goto err;
305
306         /*
307          * Issue identify, saving the result
308          */
309         xa = sili_ata_get_xfer(ap, atx);
310         xa->complete = sili_ata_dummy_done;
311         xa->data = &at->at_identify;
312         xa->datalen = sizeof(at->at_identify);
313         xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
314         xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
315
316         switch(at->at_type) {
317         case ATA_PORT_T_DISK:
318                 xa->fis->command = ATA_C_IDENTIFY;
319                 type = "DISK";
320                 break;
321         case ATA_PORT_T_ATAPI:
322                 xa->fis->command = ATA_C_ATAPI_IDENTIFY;
323                 xa->flags |= ATA_F_AUTOSENSE;
324                 type = "ATAPI";
325                 break;
326         default:
327                 xa->fis->command = ATA_C_ATAPI_IDENTIFY;
328                 type = "UNKNOWN(ATAPI?)";
329                 break;
330         }
331         xa->fis->features = 0;
332         xa->fis->device = 0;
333         xa->timeout = 1000;
334
335         if (sili_ata_cmd(xa) != ATA_S_COMPLETE) {
336                 kprintf("%s: Detected %s device but unable to IDENTIFY\n",
337                         ATANAME(ap, atx), type);
338                 sili_ata_put_xfer(xa);
339                 goto err;
340         }
341         sili_ata_put_xfer(xa);
342
343         ata_fix_identify(&at->at_identify);
344
345         /*
346          * Read capacity using SATA probe info.
347          */
348         if (le16toh(at->at_identify.cmdset83) & 0x0400) {
349                 /* LBA48 feature set supported */
350                 capacity = 0;
351                 for (i = 3; i >= 0; --i) {
352                         capacity <<= 16;
353                         capacity +=
354                             le16toh(at->at_identify.addrsecxt[i]);
355                 }
356         } else {
357                 capacity = le16toh(at->at_identify.addrsec[1]);
358                 capacity <<= 16;
359                 capacity += le16toh(at->at_identify.addrsec[0]);
360         }
361         at->at_capacity = capacity;
362         if (atx == NULL)
363                 ap->ap_probe = ATA_PROBE_GOOD;
364
365         capacity_bytes = capacity * 512;
366
367         /*
368          * Negotiate NCQ, throw away any ata_xfer's beyond the negotiated
369          * number of slots and limit the number of CAM ccb's to one less
370          * so we always have a slot available for recovery.
371          *
372          * NCQ is not used if ap_ncqdepth is 1 or the host controller does
373          * not support it, and in that case the driver can handle extra
374          * ccb's.
375          *
376          * NCQ is currently used only with direct-attached disks.  It is
377          * not used with port multipliers or direct-attached ATAPI devices.
378          *
379          * Remember at least one extra CCB needs to be reserved for the
380          * error ccb.
381          */
382         if ((ap->ap_sc->sc_flags & SILI_F_NCQ) &&
383             at->at_type == ATA_PORT_T_DISK &&
384             (le16toh(at->at_identify.satacap) & (1 << 8))) {
385                 at->at_ncqdepth = (le16toh(at->at_identify.qdepth) & 0x1F) + 1;
386                 devncqdepth = at->at_ncqdepth;
387                 if (at->at_ncqdepth > ap->ap_sc->sc_ncmds)
388                         at->at_ncqdepth = ap->ap_sc->sc_ncmds;
389                 if (at->at_ncqdepth > 1) {
390                         for (i = 0; i < ap->ap_sc->sc_ncmds; ++i) {
391                                 xa = sili_ata_get_xfer(ap, atx);
392                                 if (xa->tag < at->at_ncqdepth) {
393                                         xa->state = ATA_S_COMPLETE;
394                                         sili_ata_put_xfer(xa);
395                                 }
396                         }
397                         if (at->at_ncqdepth >= ap->ap_sc->sc_ncmds) {
398                                 cam_devq_resize(ap->ap_sim->devq,
399                                                 at->at_ncqdepth - 1);
400                         }
401                 }
402         } else {
403                 devncqdepth = 0;
404         }
405
406         /*
407          * Make the model string a bit more presentable
408          */
409         for (model_len = 40; model_len; --model_len) {
410                 if (at->at_identify.model[model_len-1] == ' ')
411                         continue;
412                 if (at->at_identify.model[model_len-1] == 0)
413                         continue;
414                 break;
415         }
416
417         /*
418          * Generate informatiive strings.
419          *
420          * NOTE: We do not automatically set write caching, lookahead,
421          *       or the security state for ATAPI devices.
422          */
423         if (at->at_identify.cmdset82 & ATA_IDENTIFY_WRITECACHE) {
424                 if (at->at_identify.features85 & ATA_IDENTIFY_WRITECACHE)
425                         wcstr = "enabled";
426                 else if (at->at_type == ATA_PORT_T_ATAPI)
427                         wcstr = "disabled";
428                 else
429                         wcstr = "enabling";
430         } else {
431                     wcstr = "notsupp";
432         }
433
434         if (at->at_identify.cmdset82 & ATA_IDENTIFY_LOOKAHEAD) {
435                 if (at->at_identify.features85 & ATA_IDENTIFY_LOOKAHEAD)
436                         rastr = "enabled";
437                 else if (at->at_type == ATA_PORT_T_ATAPI)
438                         rastr = "disabled";
439                 else
440                         rastr = "enabling";
441         } else {
442                     rastr = "notsupp";
443         }
444
445         if (at->at_identify.cmdset82 & ATA_IDENTIFY_SECURITY) {
446                 if (at->at_identify.securestatus & ATA_SECURE_FROZEN)
447                         scstr = "frozen";
448                 else if (at->at_type == ATA_PORT_T_ATAPI)
449                         scstr = "unfrozen";
450                 else if (SiliNoFeatures & (1 << ap->ap_num))
451                         scstr = "<disabled>";
452                 else
453                         scstr = "freezing";
454         } else {
455                     scstr = "notsupp";
456         }
457
458         kprintf("%s: Found %s \"%*.*s %8.8s\" serial=\"%20.20s\"\n"
459                 "%s: tags=%d/%d satacap=%04x satafea=%04x NCQ=%s "
460                 "capacity=%lld.%02dMB\n",
461
462                 ATANAME(ap, atx),
463                 type,
464                 model_len, model_len,
465                 at->at_identify.model,
466                 at->at_identify.firmware,
467                 at->at_identify.serial,
468
469                 ATANAME(ap, atx),
470                 devncqdepth, ap->ap_sc->sc_ncmds,
471                 at->at_identify.satacap,
472                 at->at_identify.satafsup,
473                 (at->at_ncqdepth > 1 ? "YES" : "NO"),
474                 (long long)capacity_bytes / (1024 * 1024),
475                 (int)(capacity_bytes % (1024 * 1024)) * 100 / (1024 * 1024)
476         );
477         kprintf("%s: f85=%04x f86=%04x f87=%04x WC=%s RA=%s SEC=%s\n",
478                 ATANAME(ap, atx),
479                 at->at_identify.features85,
480                 at->at_identify.features86,
481                 at->at_identify.features87,
482                 wcstr,
483                 rastr,
484                 scstr
485         );
486
487         /*
488          * Additional type-specific probing
489          */
490         switch(at->at_type) {
491         case ATA_PORT_T_DISK:
492                 error = sili_cam_probe_disk(ap, atx);
493                 break;
494         case ATA_PORT_T_ATAPI:
495                 error = sili_cam_probe_atapi(ap, atx);
496                 break;
497         default:
498                 error = EIO;
499                 break;
500         }
501 err:
502         kprintf("%s: CAM PROBE %d\n", ATANAME(ap, atx), error);
503         if (error) {
504                 at->at_probe = ATA_PROBE_FAILED;
505                 if (atx == NULL)
506                         ap->ap_probe = at->at_probe;
507         } else {
508                 at->at_probe = ATA_PROBE_GOOD;
509                 if (atx == NULL)
510                         ap->ap_probe = at->at_probe;
511         }
512         return (error);
513 }
514
515 /*
516  * DISK-specific probe after initial ident
517  */
518 static int
519 sili_cam_probe_disk(struct sili_port *ap, struct ata_port *atx)
520 {
521         struct ata_port *at;
522         struct ata_xfer *xa;
523
524         at = atx ? atx : ap->ap_ata;
525
526         /*
527          * Enable write cache if supported
528          *
529          * NOTE: "WD My Book" external disk devices have a very poor
530          *       daughter board between the the ESATA and the HD.  Sending
531          *       any ATA_C_SET_FEATURES commands will break the hardware port
532          *       with a fatal protocol error.  However, this device also
533          *       indicates that WRITECACHE is already on and READAHEAD is
534          *       not supported so we avoid the issue.
535          */
536         if ((at->at_identify.cmdset82 & ATA_IDENTIFY_WRITECACHE) &&
537             (at->at_identify.features85 & ATA_IDENTIFY_WRITECACHE) == 0) {
538                 xa = sili_ata_get_xfer(ap, atx);
539                 xa->complete = sili_ata_dummy_done;
540                 xa->fis->command = ATA_C_SET_FEATURES;
541                 /*xa->fis->features = ATA_SF_WRITECACHE_EN;*/
542                 xa->fis->features = ATA_SF_LOOKAHEAD_EN;
543                 xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
544                 xa->fis->device = 0;
545                 xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
546                 xa->timeout = 1000;
547                 xa->datalen = 0;
548                 if (sili_ata_cmd(xa) == ATA_S_COMPLETE)
549                         at->at_features |= ATA_PORT_F_WCACHE;
550                 else
551                         kprintf("%s: Unable to enable write-caching\n",
552                                 ATANAME(ap, atx));
553                 sili_ata_put_xfer(xa);
554         }
555
556         /*
557          * Enable readahead if supported
558          */
559         if ((at->at_identify.cmdset82 & ATA_IDENTIFY_LOOKAHEAD) &&
560             (at->at_identify.features85 & ATA_IDENTIFY_LOOKAHEAD) == 0) {
561                 xa = sili_ata_get_xfer(ap, atx);
562                 xa->complete = sili_ata_dummy_done;
563                 xa->fis->command = ATA_C_SET_FEATURES;
564                 xa->fis->features = ATA_SF_LOOKAHEAD_EN;
565                 xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
566                 xa->fis->device = 0;
567                 xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
568                 xa->timeout = 1000;
569                 xa->datalen = 0;
570                 if (sili_ata_cmd(xa) == ATA_S_COMPLETE)
571                         at->at_features |= ATA_PORT_F_RAHEAD;
572                 else
573                         kprintf("%s: Unable to enable read-ahead\n",
574                                 ATANAME(ap, atx));
575                 sili_ata_put_xfer(xa);
576         }
577
578         /*
579          * FREEZE LOCK the device so malicious users can't lock it on us.
580          * As there is no harm in issuing this to devices that don't
581          * support the security feature set we just send it, and don't bother
582          * checking if the device sends a command abort to tell us it doesn't
583          * support it
584          */
585         if ((at->at_identify.cmdset82 & ATA_IDENTIFY_SECURITY) &&
586             (at->at_identify.securestatus & ATA_SECURE_FROZEN) == 0 &&
587             (SiliNoFeatures & (1 << ap->ap_num)) == 0) {
588                 xa = sili_ata_get_xfer(ap, atx);
589                 xa->complete = sili_ata_dummy_done;
590                 xa->fis->command = ATA_C_SEC_FREEZE_LOCK;
591                 xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
592                 xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
593                 xa->timeout = 1000;
594                 xa->datalen = 0;
595                 if (sili_ata_cmd(xa) == ATA_S_COMPLETE)
596                         at->at_features |= ATA_PORT_F_FRZLCK;
597                 else
598                         kprintf("%s: Unable to set security freeze\n",
599                                 ATANAME(ap, atx));
600                 sili_ata_put_xfer(xa);
601         }
602
603         return (0);
604 }
605
606 /*
607  * ATAPI-specific probe after initial ident
608  */
609 static int
610 sili_cam_probe_atapi(struct sili_port *ap, struct ata_port *atx)
611 {
612         return(0);
613 }
614
615 /*
616  * Fix byte ordering so buffers can be accessed as
617  * strings.
618  */
619 static void
620 ata_fix_identify(struct ata_identify *id)
621 {
622         u_int16_t       *swap;
623         int             i;
624
625         swap = (u_int16_t *)id->serial;
626         for (i = 0; i < sizeof(id->serial) / sizeof(u_int16_t); i++)
627                 swap[i] = bswap16(swap[i]);
628
629         swap = (u_int16_t *)id->firmware;
630         for (i = 0; i < sizeof(id->firmware) / sizeof(u_int16_t); i++)
631                 swap[i] = bswap16(swap[i]);
632
633         swap = (u_int16_t *)id->model;
634         for (i = 0; i < sizeof(id->model) / sizeof(u_int16_t); i++)
635                 swap[i] = bswap16(swap[i]);
636 }
637
638 /*
639  * Dummy done callback for xa.
640  */
641 static void
642 sili_ata_dummy_done(struct ata_xfer *xa)
643 {
644 }
645
646 /*
647  * Use an engineering request to initiate a target scan for devices
648  * behind a port multiplier.
649  *
650  * An asynchronous bus scan is used to avoid reentrancy issues.
651  */
652 static void
653 sili_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
654 {
655         struct sili_port *ap = ccb->ccb_h.sim_priv.entries[0].ptr;
656
657         if (ccb->ccb_h.func_code == XPT_SCAN_BUS) {
658                 kprintf("%s: CAM RESCAN CALLBACK\n", PORTNAME(ap));
659                 ap->ap_flags &= ~AP_F_SCAN_RUNNING;
660                 if (ap->ap_flags & AP_F_SCAN_REQUESTED) {
661                         ap->ap_flags &= ~AP_F_SCAN_REQUESTED;
662                         sili_cam_rescan(ap);
663                 }
664                 ap->ap_flags |= AP_F_SCAN_COMPLETED;
665                 wakeup(&ap->ap_flags);
666         }
667         xpt_free_ccb(ccb);
668 }
669
670 static void
671 sili_cam_rescan(struct sili_port *ap)
672 {
673         struct cam_path *path;
674         union ccb *ccb;
675         int status;
676         int i;
677
678         kprintf("%s: CAM RESCAN-A\n", PORTNAME(ap));
679         if (ap->ap_flags & AP_F_SCAN_RUNNING) {
680                 ap->ap_flags |= AP_F_SCAN_REQUESTED;
681                 return;
682         }
683         ap->ap_flags |= AP_F_SCAN_RUNNING;
684         for (i = 0; i < SILI_MAX_PMPORTS; ++i) {
685                 ap->ap_ata[i].at_features |= ATA_PORT_F_RESCAN;
686         }
687
688         status = xpt_create_path(&path, xpt_periph, cam_sim_path(ap->ap_sim),
689                                  CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
690         if (status != CAM_REQ_CMP)
691                 return;
692
693         ccb = xpt_alloc_ccb();
694         xpt_setup_ccb(&ccb->ccb_h, path, 5);    /* 5 = low priority */
695         ccb->ccb_h.func_code = XPT_ENG_EXEC;
696         ccb->ccb_h.cbfcnp = sili_cam_rescan_callback;
697         ccb->ccb_h.sim_priv.entries[0].ptr = ap;
698         ccb->crcn.flags = CAM_FLAG_NONE;
699         xpt_action_async(ccb);
700 }
701
702 static void
703 sili_xpt_rescan(struct sili_port *ap)
704 {
705         struct cam_path *path;
706         union ccb *ccb;
707         int status;
708
709         kprintf("%s: CAM RESCAN-B\n", PORTNAME(ap));
710         status = xpt_create_path(&path, xpt_periph, cam_sim_path(ap->ap_sim),
711                                  CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
712         if (status != CAM_REQ_CMP)
713                 return;
714
715         ccb = xpt_alloc_ccb();
716         xpt_setup_ccb(&ccb->ccb_h, path, 5);    /* 5 = low priority */
717         ccb->ccb_h.func_code = XPT_SCAN_BUS;
718         ccb->ccb_h.cbfcnp = sili_cam_rescan_callback;
719         ccb->ccb_h.sim_priv.entries[0].ptr = ap;
720         ccb->crcn.flags = CAM_FLAG_NONE;
721         xpt_action_async(ccb);
722 }
723
724 /*
725  * Action function - dispatch command
726  */
727 static
728 void
729 sili_xpt_action(struct cam_sim *sim, union ccb *ccb)
730 {
731         struct sili_port *ap;
732         struct ata_port  *at, *atx;
733         struct ccb_hdr *ccbh;
734         int unit;
735
736         /* XXX lock */
737         ap = cam_sim_softc(sim);
738         at = ap->ap_ata;
739         atx = NULL;
740         KKASSERT(ap != NULL);
741         ccbh = &ccb->ccb_h;
742         unit = cam_sim_unit(sim);
743
744         /*
745          * Early failure checks.  These checks do not apply to XPT_PATH_INQ,
746          * otherwise the bus rescan will not remove the dead devices when
747          * unplugging a PM.
748          *
749          * For non-wildcards we have one target (0) and one lun (0),
750          * unless we have a port multiplier.
751          *
752          * A wildcard target indicates only the general bus is being
753          * probed.
754          *
755          * Calculate at and atx.  at is always non-NULL.  atx is only
756          * non-NULL for direct-attached devices.  It will be NULL for
757          * devices behind a port multiplier.
758          *
759          * XXX What do we do with a LUN wildcard?
760          */
761         if (ccbh->target_id != CAM_TARGET_WILDCARD &&
762             ccbh->func_code != XPT_PATH_INQ) {
763                 if (ap->ap_type == ATA_PORT_T_NONE) {
764                         ccbh->status = CAM_DEV_NOT_THERE;
765                         xpt_done(ccb);
766                         return;
767                 }
768                 if (ccbh->target_id < 0 || ccbh->target_id >= ap->ap_pmcount) {
769                         ccbh->status = CAM_DEV_NOT_THERE;
770                         xpt_done(ccb);
771                         return;
772                 }
773                 at += ccbh->target_id;
774                 if (ap->ap_type == ATA_PORT_T_PM)
775                         atx = at;
776
777                 if (ccbh->target_lun != CAM_LUN_WILDCARD && ccbh->target_lun) {
778                         ccbh->status = CAM_DEV_NOT_THERE;
779                         xpt_done(ccb);
780                         return;
781                 }
782         }
783
784         /*
785          * Switch on the meta XPT command
786          */
787         switch(ccbh->func_code) {
788         case XPT_ENG_EXEC:
789                 /*
790                  * This routine is called after a port multiplier has been
791                  * probed.
792                  */
793                 ccbh->status = CAM_REQ_CMP;
794                 sili_os_lock_port(ap);
795                 sili_port_state_machine(ap, 0);
796                 sili_os_unlock_port(ap);
797                 xpt_done(ccb);
798                 sili_xpt_rescan(ap);
799                 break;
800         case XPT_PATH_INQ:
801                 /*
802                  * This command always succeeds, otherwise the bus scan
803                  * will not detach dead devices.
804                  */
805                 ccb->cpi.version_num = 1;
806                 ccb->cpi.hba_inquiry = 0;
807                 ccb->cpi.target_sprt = 0;
808                 ccb->cpi.hba_misc = PIM_SEQSCAN;
809                 ccb->cpi.hba_eng_cnt = 0;
810                 bzero(ccb->cpi.vuhba_flags, sizeof(ccb->cpi.vuhba_flags));
811                 ccb->cpi.max_target = SILI_MAX_PMPORTS - 1;
812                 ccb->cpi.max_lun = 0;
813                 ccb->cpi.async_flags = 0;
814                 ccb->cpi.hpath_id = 0;
815                 ccb->cpi.initiator_id = SILI_MAX_PMPORTS - 1;
816                 ccb->cpi.unit_number = cam_sim_unit(sim);
817                 ccb->cpi.bus_id = cam_sim_bus(sim);
818                 ccb->cpi.base_transfer_speed = 150000;
819                 ccb->cpi.transport = XPORT_SATA;
820                 ccb->cpi.transport_version = 1;
821                 ccb->cpi.protocol = PROTO_SCSI;
822                 ccb->cpi.protocol_version = SCSI_REV_2;
823
824                 ccbh->status = CAM_REQ_CMP;
825                 if (ccbh->target_id == CAM_TARGET_WILDCARD) {
826                         sili_os_lock_port(ap);
827                         sili_port_state_machine(ap, 0);
828                         sili_os_unlock_port(ap);
829                 } else {
830                         switch(sili_pread(ap, SILI_PREG_SSTS) &
831                                SILI_PREG_SSTS_SPD) {
832                         case SILI_PREG_SSTS_SPD_GEN1:
833                                 ccb->cpi.base_transfer_speed = 150000;
834                                 break;
835                         case SILI_PREG_SSTS_SPD_GEN2:
836                                 ccb->cpi.base_transfer_speed = 300000;
837                                 break;
838                         default:
839                                 /* unknown */
840                                 ccb->cpi.base_transfer_speed = 1000;
841                                 break;
842                         }
843 #if 0
844                         if (ap->ap_type == ATA_PORT_T_NONE)
845                                 ccbh->status = CAM_DEV_NOT_THERE;
846 #endif
847                 }
848                 xpt_done(ccb);
849                 break;
850         case XPT_RESET_DEV:
851                 sili_os_lock_port(ap);
852                 if (ap->ap_type == ATA_PORT_T_NONE) {
853                         ccbh->status = CAM_DEV_NOT_THERE;
854                 } else {
855                         sili_port_reset(ap, atx, 0);
856                         ccbh->status = CAM_REQ_CMP;
857                 }
858                 sili_os_unlock_port(ap);
859                 xpt_done(ccb);
860                 break;
861         case XPT_RESET_BUS:
862                 sili_os_lock_port(ap);
863                 sili_port_reset(ap, NULL, 1);
864                 sili_os_unlock_port(ap);
865                 ccbh->status = CAM_REQ_CMP;
866                 xpt_done(ccb);
867                 break;
868         case XPT_SET_TRAN_SETTINGS:
869                 ccbh->status = CAM_FUNC_NOTAVAIL;
870                 xpt_done(ccb);
871                 break;
872         case XPT_GET_TRAN_SETTINGS:
873                 ccb->cts.protocol = PROTO_SCSI;
874                 ccb->cts.protocol_version = SCSI_REV_2;
875                 ccb->cts.transport = XPORT_SATA;
876                 ccb->cts.transport_version = XPORT_VERSION_UNSPECIFIED;
877                 ccb->cts.proto_specific.valid = 0;
878                 ccb->cts.xport_specific.valid = 0;
879                 ccbh->status = CAM_REQ_CMP;
880                 xpt_done(ccb);
881                 break;
882         case XPT_CALC_GEOMETRY:
883                 cam_calc_geometry(&ccb->ccg, 1);
884                 xpt_done(ccb);
885                 break;
886         case XPT_SCSI_IO:
887                 /*
888                  * Our parallel startup code might have only probed through
889                  * to the IDENT, so do the last step if necessary.
890                  */
891                 if (at->at_probe == ATA_PROBE_NEED_IDENT)
892                         sili_cam_probe(ap, atx);
893                 if (at->at_probe != ATA_PROBE_GOOD) {
894                         ccbh->status = CAM_DEV_NOT_THERE;
895                         xpt_done(ccb);
896                         break;
897                 }
898                 switch(at->at_type) {
899                 case ATA_PORT_T_DISK:
900                         sili_xpt_scsi_disk_io(ap, atx, ccb);
901                         break;
902                 case ATA_PORT_T_ATAPI:
903                         sili_xpt_scsi_atapi_io(ap, atx, ccb);
904                         break;
905                 default:
906                         ccbh->status = CAM_REQ_INVALID;
907                         xpt_done(ccb);
908                         break;
909                 }
910                 break;
911         default:
912                 ccbh->status = CAM_REQ_INVALID;
913                 xpt_done(ccb);
914                 break;
915         }
916 }
917
918 /*
919  * Poll function.
920  *
921  * Generally this function gets called heavily when interrupts might be
922  * non-operational, during a halt/reboot or panic.
923  */
924 static
925 void
926 sili_xpt_poll(struct cam_sim *sim)
927 {
928         struct sili_port *ap;
929
930         ap = cam_sim_softc(sim);
931         crit_enter();
932         sili_os_lock_port(ap);
933         sili_port_intr(ap, 1);
934         sili_os_unlock_port(ap);
935         crit_exit();
936 }
937
938 /*
939  * Convert the SCSI command in ccb to an ata_xfer command in xa
940  * for ATA_PORT_T_DISK operations.  Set the completion function
941  * to convert the response back, then dispatch to the OpenBSD SILI
942  * layer.
943  *
944  * SILI DISK commands only support a limited command set, and we
945  * fake additional commands to make it play nice with the CAM subsystem.
946  */
947 static
948 void
949 sili_xpt_scsi_disk_io(struct sili_port *ap, struct ata_port *atx,
950                       union ccb *ccb)
951 {
952         struct ccb_hdr *ccbh;
953         struct ccb_scsiio *csio;
954         struct ata_xfer *xa;
955         struct ata_port *at;
956         struct ata_fis_h2d *fis;
957         scsi_cdb_t cdb;
958         union scsi_data *rdata;
959         int rdata_len;
960         u_int64_t capacity;
961         u_int64_t lba;
962         u_int32_t count;
963
964         ccbh = &ccb->csio.ccb_h;
965         csio = &ccb->csio;
966         at = atx ? atx : &ap->ap_ata[0];
967
968         /*
969          * XXX not passing NULL at for direct attach!
970          */
971         xa = sili_ata_get_xfer(ap, atx);
972         rdata = (void *)csio->data_ptr;
973         rdata_len = csio->dxfer_len;
974
975         /*
976          * Build the FIS or process the csio to completion.
977          */
978         cdb = (void *)((ccbh->flags & CAM_CDB_POINTER) ?
979                         csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes);
980
981         switch(cdb->generic.opcode) {
982         case REQUEST_SENSE:
983                 /*
984                  * Auto-sense everything, so explicit sense requests
985                  * return no-sense.
986                  */
987                 ccbh->status = CAM_SCSI_STATUS_ERROR;
988                 break;
989         case INQUIRY:
990                 /*
991                  * Inquiry supported features
992                  *
993                  * [opcode, byte2, page_code, length, control]
994                  */
995                 if (cdb->inquiry.byte2 & SI_EVPD) {
996                         switch(cdb->inquiry.page_code) {
997                         case SVPD_SUPPORTED_PAGE_LIST:
998                                 /* XXX atascsi_disk_vpd_supported */
999                         case SVPD_UNIT_SERIAL_NUMBER:
1000                                 /* XXX atascsi_disk_vpd_serial */
1001                         case SVPD_UNIT_DEVID:
1002                                 /* XXX atascsi_disk_vpd_ident */
1003                         default:
1004                                 ccbh->status = CAM_FUNC_NOTAVAIL;
1005                                 break;
1006                         }
1007                 } else {
1008                         bzero(rdata, rdata_len);
1009                         if (rdata_len < SHORT_INQUIRY_LENGTH) {
1010                                 ccbh->status = CAM_CCB_LEN_ERR;
1011                                 break;
1012                         }
1013                         if (rdata_len > sizeof(rdata->inquiry_data))
1014                                 rdata_len = sizeof(rdata->inquiry_data);
1015                         rdata->inquiry_data.device = T_DIRECT;
1016                         rdata->inquiry_data.version = SCSI_REV_SPC2;
1017                         rdata->inquiry_data.response_format = 2;
1018                         rdata->inquiry_data.additional_length = 32;
1019                         bcopy("SATA    ", rdata->inquiry_data.vendor, 8);
1020                         bcopy(at->at_identify.model,
1021                               rdata->inquiry_data.product,
1022                               sizeof(rdata->inquiry_data.product));
1023                         bcopy(at->at_identify.firmware,
1024                               rdata->inquiry_data.revision,
1025                               sizeof(rdata->inquiry_data.revision));
1026                         ccbh->status = CAM_REQ_CMP;
1027                 }
1028                 break;
1029         case READ_CAPACITY_16:
1030                 if (cdb->read_capacity_16.service_action != SRC16_SERVICE_ACTION) {
1031                         ccbh->status = CAM_REQ_INVALID;
1032                         break;
1033                 }
1034                 if (rdata_len < sizeof(rdata->read_capacity_data_16)) {
1035                         ccbh->status = CAM_CCB_LEN_ERR;
1036                         break;
1037                 }
1038                 /* fall through */
1039         case READ_CAPACITY:
1040                 if (rdata_len < sizeof(rdata->read_capacity_data)) {
1041                         ccbh->status = CAM_CCB_LEN_ERR;
1042                         break;
1043                 }
1044
1045                 capacity = at->at_capacity;
1046
1047                 bzero(rdata, rdata_len);
1048                 if (cdb->generic.opcode == READ_CAPACITY) {
1049                         rdata_len = sizeof(rdata->read_capacity_data);
1050                         if (capacity > 0xFFFFFFFFU)
1051                                 capacity = 0xFFFFFFFFU;
1052                         bzero(&rdata->read_capacity_data, rdata_len);
1053                         scsi_ulto4b((u_int32_t)capacity - 1,
1054                                     rdata->read_capacity_data.addr);
1055                         scsi_ulto4b(512, rdata->read_capacity_data.length);
1056                 } else {
1057                         rdata_len = sizeof(rdata->read_capacity_data_16);
1058                         bzero(&rdata->read_capacity_data_16, rdata_len);
1059                         scsi_u64to8b(capacity - 1,
1060                                      rdata->read_capacity_data_16.addr);
1061                         scsi_ulto4b(512, rdata->read_capacity_data_16.length);
1062                 }
1063                 ccbh->status = CAM_REQ_CMP;
1064                 break;
1065         case SYNCHRONIZE_CACHE:
1066                 /*
1067                  * Synchronize cache.  Specification says this can take
1068                  * greater then 30 seconds so give it at least 45.
1069                  */
1070                 fis = xa->fis;
1071                 fis->flags = ATA_H2D_FLAGS_CMD;
1072                 fis->command = ATA_C_FLUSH_CACHE;
1073                 fis->device = 0;
1074                 if (xa->timeout < 45000)
1075                         xa->timeout = 45000;
1076                 xa->datalen = 0;
1077                 xa->flags = ATA_F_READ;
1078                 xa->complete = sili_ata_complete_disk_synchronize_cache;
1079                 break;
1080         case TEST_UNIT_READY:
1081         case START_STOP_UNIT:
1082         case PREVENT_ALLOW:
1083                 /*
1084                  * Just silently return success
1085                  */
1086                 ccbh->status = CAM_REQ_CMP;
1087                 rdata_len = 0;
1088                 break;
1089         case ATA_PASS_12:
1090         case ATA_PASS_16:
1091                 /*
1092                  * XXX implement pass-through
1093                  */
1094                 ccbh->status = CAM_FUNC_NOTAVAIL;
1095                 break;
1096         default:
1097                 switch(cdb->generic.opcode) {
1098                 case READ_6:
1099                         lba = scsi_3btoul(cdb->rw_6.addr) & 0x1FFFFF;
1100                         count = cdb->rw_6.length ? cdb->rw_6.length : 0x100;
1101                         xa->flags = ATA_F_READ;
1102                         break;
1103                 case READ_10:
1104                         lba = scsi_4btoul(cdb->rw_10.addr);
1105                         count = scsi_2btoul(cdb->rw_10.length);
1106                         xa->flags = ATA_F_READ;
1107                         break;
1108                 case READ_12:
1109                         lba = scsi_4btoul(cdb->rw_12.addr);
1110                         count = scsi_4btoul(cdb->rw_12.length);
1111                         xa->flags = ATA_F_READ;
1112                         break;
1113                 case READ_16:
1114                         lba = scsi_8btou64(cdb->rw_16.addr);
1115                         count = scsi_4btoul(cdb->rw_16.length);
1116                         xa->flags = ATA_F_READ;
1117                         break;
1118                 case WRITE_6:
1119                         lba = scsi_3btoul(cdb->rw_6.addr) & 0x1FFFFF;
1120                         count = cdb->rw_6.length ? cdb->rw_6.length : 0x100;
1121                         xa->flags = ATA_F_WRITE;
1122                         break;
1123                 case WRITE_10:
1124                         lba = scsi_4btoul(cdb->rw_10.addr);
1125                         count = scsi_2btoul(cdb->rw_10.length);
1126                         xa->flags = ATA_F_WRITE;
1127                         break;
1128                 case WRITE_12:
1129                         lba = scsi_4btoul(cdb->rw_12.addr);
1130                         count = scsi_4btoul(cdb->rw_12.length);
1131                         xa->flags = ATA_F_WRITE;
1132                         break;
1133                 case WRITE_16:
1134                         lba = scsi_8btou64(cdb->rw_16.addr);
1135                         count = scsi_4btoul(cdb->rw_16.length);
1136                         xa->flags = ATA_F_WRITE;
1137                         break;
1138                 default:
1139                         ccbh->status = CAM_REQ_INVALID;
1140                         break;
1141                 }
1142                 if (ccbh->status != CAM_REQ_INPROG)
1143                         break;
1144
1145                 fis = xa->fis;
1146                 fis->flags = ATA_H2D_FLAGS_CMD;
1147                 fis->lba_low = (u_int8_t)lba;
1148                 fis->lba_mid = (u_int8_t)(lba >> 8);
1149                 fis->lba_high = (u_int8_t)(lba >> 16);
1150                 fis->device = ATA_H2D_DEVICE_LBA;
1151
1152                 /*
1153                  * NCQ only for direct-attached disks, do not currently
1154                  * try to use NCQ with port multipliers.
1155                  *
1156                  * XXX fixme SII chip can do NCQ w/ port multipliers.
1157                  */
1158                 if (at->at_ncqdepth > 1 &&
1159                     at->at_type == ATA_PORT_T_DISK &&
1160                     (ap->ap_sc->sc_flags & SILI_F_NCQ) &&
1161                     (ccbh->flags & CAM_POLLED) == 0) {
1162                         /*
1163                          * Use NCQ - always uses 48 bit addressing
1164                          */
1165                         xa->flags |= ATA_F_NCQ;
1166                         fis->command = (xa->flags & ATA_F_WRITE) ?
1167                                         ATA_C_WRITE_FPDMA : ATA_C_READ_FPDMA;
1168                         fis->lba_low_exp = (u_int8_t)(lba >> 24);
1169                         fis->lba_mid_exp = (u_int8_t)(lba >> 32);
1170                         fis->lba_high_exp = (u_int8_t)(lba >> 40);
1171                         fis->sector_count = xa->tag << 3;
1172                         fis->features = (u_int8_t)count;
1173                         fis->features_exp = (u_int8_t)(count >> 8);
1174                 } else if (count > 0x100 || lba > 0xFFFFFFFFU) {
1175                         /*
1176                          * Use LBA48
1177                          */
1178                         fis->command = (xa->flags & ATA_F_WRITE) ?
1179                                         ATA_C_WRITEDMA_EXT : ATA_C_READDMA_EXT;
1180                         fis->lba_low_exp = (u_int8_t)(lba >> 24);
1181                         fis->lba_mid_exp = (u_int8_t)(lba >> 32);
1182                         fis->lba_high_exp = (u_int8_t)(lba >> 40);
1183                         fis->sector_count = (u_int8_t)count;
1184                         fis->sector_count_exp = (u_int8_t)(count >> 8);
1185                 } else {
1186                         /*
1187                          * Use LBA
1188                          *
1189                          * NOTE: 256 sectors is supported, stored as 0.
1190                          */
1191                         fis->command = (xa->flags & ATA_F_WRITE) ?
1192                                         ATA_C_WRITEDMA : ATA_C_READDMA;
1193                         fis->device |= (u_int8_t)(lba >> 24) & 0x0F;
1194                         fis->sector_count = (u_int8_t)count;
1195                 }
1196
1197                 xa->data = csio->data_ptr;
1198                 xa->datalen = csio->dxfer_len;
1199                 xa->complete = sili_ata_complete_disk_rw;
1200                 xa->timeout = ccbh->timeout;    /* milliseconds */
1201                 if (ccbh->flags & CAM_POLLED)
1202                         xa->flags |= ATA_F_POLL;
1203                 break;
1204         }
1205
1206         /*
1207          * If the request is still in progress the xa and FIS have
1208          * been set up and must be dispatched.  Otherwise the request
1209          * is complete.
1210          */
1211         if (ccbh->status == CAM_REQ_INPROG) {
1212                 KKASSERT(xa->complete != NULL);
1213                 xa->atascsi_private = ccb;
1214                 ccb->ccb_h.sim_priv.entries[0].ptr = ap;
1215                 sili_os_lock_port(ap);
1216                 fis->flags |= at->at_target;
1217                 sili_ata_cmd(xa);
1218                 sili_os_unlock_port(ap);
1219         } else {
1220                 sili_ata_put_xfer(xa);
1221                 xpt_done(ccb);
1222         }
1223 }
1224
1225 /*
1226  * Convert the SCSI command in ccb to an ata_xfer command in xa
1227  * for ATA_PORT_T_ATAPI operations.  Set the completion function
1228  * to convert the response back, then dispatch to the OpenBSD SILI
1229  * layer.
1230  */
1231 static
1232 void
1233 sili_xpt_scsi_atapi_io(struct sili_port *ap, struct ata_port *atx,
1234                         union ccb *ccb)
1235 {
1236         struct ccb_hdr *ccbh;
1237         struct ccb_scsiio *csio;
1238         struct ata_xfer *xa;
1239         struct ata_fis_h2d *fis;
1240         scsi_cdb_t cdbs;
1241         scsi_cdb_t cdbd;
1242         int flags;
1243         struct ata_port *at;
1244
1245         ccbh = &ccb->csio.ccb_h;
1246         csio = &ccb->csio;
1247         at = atx ? atx : &ap->ap_ata[0];
1248
1249         switch (ccbh->flags & CAM_DIR_MASK) {
1250         case CAM_DIR_IN:
1251                 flags = ATA_F_PACKET | ATA_F_READ;
1252                 break;
1253         case CAM_DIR_OUT:
1254                 flags = ATA_F_PACKET | ATA_F_WRITE;
1255                 break;
1256         case CAM_DIR_NONE:
1257                 flags = ATA_F_PACKET;
1258                 break;
1259         default:
1260                 ccbh->status = CAM_REQ_INVALID;
1261                 xpt_done(ccb);
1262                 return;
1263                 /* NOT REACHED */
1264         }
1265
1266         /*
1267          * Special handling to get the rfis back into host memory while
1268          * still allowing the Sili chip to run commands in parallel to
1269          * ATAPI devices behind a PM.
1270          */
1271         flags |= ATA_F_AUTOSENSE;
1272
1273         /*
1274          * The command has to fit in the packet command buffer.
1275          */
1276         if (csio->cdb_len < 6 || csio->cdb_len > 16) {
1277                 ccbh->status = CAM_CCB_LEN_ERR;
1278                 xpt_done(ccb);
1279                 return;
1280         }
1281
1282         /*
1283          * Initialize the XA and FIS.
1284          *
1285          * XXX not passing NULL at for direct attach!
1286          */
1287         xa = sili_ata_get_xfer(ap, atx);
1288         fis = xa->fis;
1289
1290         fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
1291         fis->command = ATA_C_PACKET;
1292         fis->device = 0;
1293         fis->sector_count = xa->tag << 3;
1294         fis->features = ATA_H2D_FEATURES_DMA |
1295                     ((flags & ATA_F_WRITE) ?
1296                     ATA_H2D_FEATURES_DIR_WRITE : ATA_H2D_FEATURES_DIR_READ);
1297         fis->lba_mid = 0x00;
1298         fis->lba_high = 0x20;
1299
1300         xa->flags = flags;
1301         xa->data = csio->data_ptr;
1302         xa->datalen = csio->dxfer_len;
1303         xa->timeout = ccbh->timeout;    /* milliseconds */
1304
1305         if (ccbh->flags & CAM_POLLED)
1306                 xa->flags |= ATA_F_POLL;
1307
1308         /*
1309          * Copy the cdb to the packetcmd buffer in the FIS using a
1310          * convenient pointer in the xa.
1311          */
1312         cdbs = (void *)((ccbh->flags & CAM_CDB_POINTER) ?
1313                         csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes);
1314         bcopy(cdbs, xa->packetcmd, csio->cdb_len);
1315
1316 #if 0
1317         kprintf("opcode %d cdb_len %d dxfer_len %d\n",
1318                 cdbs->generic.opcode,
1319                 csio->cdb_len, csio->dxfer_len);
1320 #endif
1321
1322         /*
1323          * Some ATAPI commands do not actually follow the SCSI standard.
1324          */
1325         cdbd = (void *)xa->packetcmd;
1326
1327         switch(cdbd->generic.opcode) {
1328         case INQUIRY:
1329                 /*
1330                  * Some ATAPI devices can't handle SI_EVPD being set
1331                  * for a basic inquiry (page_code == 0).
1332                  *
1333                  * Some ATAPI devices can't handle long inquiry lengths,
1334                  * don't ask me why.  Truncate the inquiry length.
1335                  */
1336                 if ((cdbd->inquiry.byte2 & SI_EVPD) &&
1337                     cdbd->inquiry.page_code == 0) {
1338                         cdbd->inquiry.byte2 &= ~SI_EVPD;
1339                 }
1340                 if (cdbd->inquiry.page_code == 0 &&
1341                     cdbd->inquiry.length > SHORT_INQUIRY_LENGTH) {
1342                         cdbd->inquiry.length = SHORT_INQUIRY_LENGTH;
1343                 }
1344                 break;
1345         case READ_6:
1346         case WRITE_6:
1347                 /*
1348                  * Convert *_6 to *_10 commands.  Most ATAPI devices
1349                  * cannot handle the SCSI READ_6 and WRITE_6 commands.
1350                  */
1351                 cdbd->rw_10.opcode |= 0x20;
1352                 cdbd->rw_10.byte2 = 0;
1353                 cdbd->rw_10.addr[0] = cdbs->rw_6.addr[0] & 0x1F;
1354                 cdbd->rw_10.addr[1] = cdbs->rw_6.addr[1];
1355                 cdbd->rw_10.addr[2] = cdbs->rw_6.addr[2];
1356                 cdbd->rw_10.addr[3] = 0;
1357                 cdbd->rw_10.reserved = 0;
1358                 cdbd->rw_10.length[0] = 0;
1359                 cdbd->rw_10.length[1] = cdbs->rw_6.length;
1360                 cdbd->rw_10.control = cdbs->rw_6.control;
1361                 break;
1362         default:
1363                 break;
1364         }
1365
1366         /*
1367          * And dispatch
1368          */
1369         xa->complete = sili_atapi_complete_cmd;
1370         xa->atascsi_private = ccb;
1371         ccb->ccb_h.sim_priv.entries[0].ptr = ap;
1372         sili_os_lock_port(ap);
1373         sili_ata_cmd(xa);
1374         sili_os_unlock_port(ap);
1375 }
1376
1377 /*
1378  * Completion function for ATA_PORT_T_DISK cache synchronization.
1379  */
1380 static
1381 void
1382 sili_ata_complete_disk_synchronize_cache(struct ata_xfer *xa)
1383 {
1384         union ccb *ccb = xa->atascsi_private;
1385         struct ccb_hdr *ccbh = &ccb->ccb_h;
1386         struct sili_port *ap = ccb->ccb_h.sim_priv.entries[0].ptr;
1387
1388         switch(xa->state) {
1389         case ATA_S_COMPLETE:
1390                 ccbh->status = CAM_REQ_CMP;
1391                 ccb->csio.scsi_status = SCSI_STATUS_OK;
1392                 break;
1393         case ATA_S_ERROR:
1394                 kprintf("%s: synchronize_cache: error\n",
1395                         ATANAME(ap, xa->at));
1396                 ccbh->status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
1397                 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
1398                 sili_ata_dummy_sense(&ccb->csio.sense_data);
1399                 break;
1400         case ATA_S_TIMEOUT:
1401                 kprintf("%s: synchronize_cache: timeout\n",
1402                         ATANAME(ap, xa->at));
1403                 ccbh->status = CAM_CMD_TIMEOUT;
1404                 break;
1405         default:
1406                 kprintf("%s: synchronize_cache: unknown state %d\n",
1407                         ATANAME(ap, xa->at), xa->state);
1408                 ccbh->status = CAM_REQ_CMP_ERR;
1409                 break;
1410         }
1411         sili_ata_put_xfer(xa);
1412         sili_os_unlock_port(ap);
1413         xpt_done(ccb);
1414         sili_os_lock_port(ap);
1415 }
1416
1417 /*
1418  * Completion function for ATA_PORT_T_DISK I/O
1419  */
1420 static
1421 void
1422 sili_ata_complete_disk_rw(struct ata_xfer *xa)
1423 {
1424         union ccb *ccb = xa->atascsi_private;
1425         struct ccb_hdr *ccbh = &ccb->ccb_h;
1426         struct sili_port *ap = ccb->ccb_h.sim_priv.entries[0].ptr;
1427
1428         switch(xa->state) {
1429         case ATA_S_COMPLETE:
1430                 ccbh->status = CAM_REQ_CMP;
1431                 ccb->csio.scsi_status = SCSI_STATUS_OK;
1432                 break;
1433         case ATA_S_ERROR:
1434                 kprintf("%s: disk_rw: error\n", ATANAME(ap, xa->at));
1435                 ccbh->status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
1436                 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
1437                 sili_ata_dummy_sense(&ccb->csio.sense_data);
1438                 break;
1439         case ATA_S_TIMEOUT:
1440                 kprintf("%s: disk_rw: timeout\n", ATANAME(ap, xa->at));
1441                 ccbh->status = CAM_CMD_TIMEOUT;
1442                 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
1443                 sili_ata_dummy_sense(&ccb->csio.sense_data);
1444                 break;
1445         default:
1446                 kprintf("%s: disk_rw: unknown state %d\n",
1447                         ATANAME(ap, xa->at), xa->state);
1448                 ccbh->status = CAM_REQ_CMP_ERR;
1449                 break;
1450         }
1451         ccb->csio.resid = xa->resid;
1452         sili_ata_put_xfer(xa);
1453         sili_os_unlock_port(ap);
1454         xpt_done(ccb);
1455         sili_os_lock_port(ap);
1456 }
1457
1458 /*
1459  * Completion function for ATA_PORT_T_ATAPI I/O
1460  *
1461  * Sense data is returned in the rfis.
1462  */
1463 static
1464 void
1465 sili_atapi_complete_cmd(struct ata_xfer *xa)
1466 {
1467         union ccb *ccb = xa->atascsi_private;
1468         struct ccb_hdr *ccbh = &ccb->ccb_h;
1469         struct sili_port *ap = ccb->ccb_h.sim_priv.entries[0].ptr;
1470         scsi_cdb_t cdb;
1471
1472         cdb = (void *)((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
1473                         ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes);
1474
1475         switch(xa->state) {
1476         case ATA_S_COMPLETE:
1477                 ccbh->status = CAM_REQ_CMP;
1478                 ccb->csio.scsi_status = SCSI_STATUS_OK;
1479                 break;
1480         case ATA_S_ERROR:
1481                 ccbh->status = CAM_SCSI_STATUS_ERROR;
1482                 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
1483                 sili_ata_atapi_sense(xa->rfis, &ccb->csio.sense_data);
1484                 break;
1485         case ATA_S_TIMEOUT:
1486                 kprintf("%s: cmd %d: timeout\n",
1487                         PORTNAME(ap), cdb->generic.opcode);
1488                 ccbh->status = CAM_CMD_TIMEOUT;
1489                 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
1490                 sili_ata_dummy_sense(&ccb->csio.sense_data);
1491                 break;
1492         default:
1493                 kprintf("%s: cmd %d: unknown state %d\n",
1494                         PORTNAME(ap), cdb->generic.opcode, xa->state);
1495                 ccbh->status = CAM_REQ_CMP_ERR;
1496                 break;
1497         }
1498         ccb->csio.resid = xa->resid;
1499         sili_ata_put_xfer(xa);
1500         sili_os_unlock_port(ap);
1501         xpt_done(ccb);
1502         sili_os_lock_port(ap);
1503 }
1504
1505 /*
1506  * Construct dummy sense data for errors on DISKs
1507  */
1508 static
1509 void
1510 sili_ata_dummy_sense(struct scsi_sense_data *sense_data)
1511 {
1512         sense_data->error_code = SSD_ERRCODE_VALID | SSD_CURRENT_ERROR;
1513         sense_data->segment = 0;
1514         sense_data->flags = SSD_KEY_MEDIUM_ERROR;
1515         sense_data->info[0] = 0;
1516         sense_data->info[1] = 0;
1517         sense_data->info[2] = 0;
1518         sense_data->info[3] = 0;
1519         sense_data->extra_len = 0;
1520 }
1521
1522 /*
1523  * Construct atapi sense data for errors on ATAPI
1524  *
1525  * The ATAPI sense data is stored in the passed rfis and must be converted
1526  * to SCSI sense data.
1527  */
1528 static
1529 void
1530 sili_ata_atapi_sense(struct ata_fis_d2h *rfis,
1531                      struct scsi_sense_data *sense_data)
1532 {
1533         sense_data->error_code = SSD_ERRCODE_VALID | SSD_CURRENT_ERROR;
1534         sense_data->segment = 0;
1535         sense_data->flags = (rfis->error & 0xF0) >> 4;
1536         if (rfis->error & 0x04)
1537                 sense_data->flags |= SSD_KEY_ILLEGAL_REQUEST;
1538         if (rfis->error & 0x02)
1539                 sense_data->flags |= SSD_EOM;
1540         if (rfis->error & 0x01)
1541                 sense_data->flags |= SSD_ILI;
1542         sense_data->info[0] = 0;
1543         sense_data->info[1] = 0;
1544         sense_data->info[2] = 0;
1545         sense_data->info[3] = 0;
1546         sense_data->extra_len = 0;
1547 }