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, §or_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 : }
|