xref: /freebsd/sys/cam/ata/ata_da.c (revision 5861f9665471e98e544f6fa3ce73c4912229ff82)
1 /*-
2  * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification, immediately at the beginning of the file.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/param.h>
31 
32 #ifdef _KERNEL
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/bio.h>
36 #include <sys/sysctl.h>
37 #include <sys/taskqueue.h>
38 #include <sys/lock.h>
39 #include <sys/mutex.h>
40 #include <sys/conf.h>
41 #include <sys/devicestat.h>
42 #include <sys/eventhandler.h>
43 #include <sys/malloc.h>
44 #include <sys/cons.h>
45 #include <geom/geom_disk.h>
46 #endif /* _KERNEL */
47 
48 #ifndef _KERNEL
49 #include <stdio.h>
50 #include <string.h>
51 #endif /* _KERNEL */
52 
53 #include <cam/cam.h>
54 #include <cam/cam_ccb.h>
55 #include <cam/cam_periph.h>
56 #include <cam/cam_xpt_periph.h>
57 #include <cam/cam_sim.h>
58 
59 #include <cam/ata/ata_all.h>
60 
61 #ifdef _KERNEL
62 
63 #define ATA_MAX_28BIT_LBA               268435455UL
64 
65 typedef enum {
66 	ADA_STATE_NORMAL
67 } ada_state;
68 
69 typedef enum {
70 	ADA_FLAG_PACK_INVALID	= 0x001,
71 	ADA_FLAG_CAN_48BIT	= 0x002,
72 	ADA_FLAG_CAN_FLUSHCACHE	= 0x004,
73 	ADA_FLAG_CAN_NCQ		= 0x008,
74 	ADA_FLAG_TAGGED_QUEUING	= 0x010,
75 	ADA_FLAG_NEED_OTAG	= 0x020,
76 	ADA_FLAG_WENT_IDLE	= 0x040,
77 	ADA_FLAG_RETRY_UA	= 0x080,
78 	ADA_FLAG_OPEN		= 0x100,
79 	ADA_FLAG_SCTX_INIT	= 0x200
80 } ada_flags;
81 
82 typedef enum {
83 	ADA_Q_NONE		= 0x00,
84 	ADA_Q_NO_SYNC_CACHE	= 0x01,
85 	ADA_Q_NO_6_BYTE		= 0x02,
86 	ADA_Q_NO_PREVENT		= 0x04
87 } ada_quirks;
88 
89 typedef enum {
90 	ADA_CCB_PROBE		= 0x01,
91 	ADA_CCB_PROBE2		= 0x02,
92 	ADA_CCB_BUFFER_IO	= 0x03,
93 	ADA_CCB_WAITING		= 0x04,
94 	ADA_CCB_DUMP		= 0x05,
95 	ADA_CCB_TYPE_MASK	= 0x0F,
96 	ADA_CCB_RETRY_UA		= 0x10
97 } ada_ccb_state;
98 
99 /* Offsets into our private area for storing information */
100 #define ccb_state	ppriv_field0
101 #define ccb_bp		ppriv_ptr1
102 
103 struct disk_params {
104 	u_int8_t  heads;
105 	u_int32_t cylinders;
106 	u_int8_t  secs_per_track;
107 	u_int32_t secsize;	/* Number of bytes/sector */
108 	u_int64_t sectors;	/* total number sectors */
109 };
110 
111 struct ada_softc {
112 	struct	 bio_queue_head bio_queue;
113 	SLIST_ENTRY(ada_softc) links;
114 	LIST_HEAD(, ccb_hdr) pending_ccbs;
115 	ada_state state;
116 	ada_flags flags;
117 	ada_quirks quirks;
118 	int	 ordered_tag_count;
119 	int	 outstanding_cmds;
120 	struct	 disk_params params;
121 	struct	 disk *disk;
122 	union	 ccb saved_ccb;
123 	struct task		sysctl_task;
124 	struct sysctl_ctx_list	sysctl_ctx;
125 	struct sysctl_oid	*sysctl_tree;
126 	struct callout		sendordered_c;
127 };
128 
129 struct ada_quirk_entry {
130 	struct scsi_inquiry_pattern inq_pat;
131 	ada_quirks quirks;
132 };
133 
134 //static struct ada_quirk_entry ada_quirk_table[] =
135 //{
136 //};
137 
138 static	disk_strategy_t	adastrategy;
139 static	dumper_t	adadump;
140 static	periph_init_t	adainit;
141 static	void		adaasync(void *callback_arg, u_int32_t code,
142 				struct cam_path *path, void *arg);
143 static	void		adasysctlinit(void *context, int pending);
144 static	periph_ctor_t	adaregister;
145 static	periph_dtor_t	adacleanup;
146 static	periph_start_t	adastart;
147 static	periph_oninv_t	adaoninvalidate;
148 static	void		adadone(struct cam_periph *periph,
149 			       union ccb *done_ccb);
150 static  int		adaerror(union ccb *ccb, u_int32_t cam_flags,
151 				u_int32_t sense_flags);
152 static void		adasetgeom(struct cam_periph *periph,
153 				struct ccb_getdev *cgd);
154 static timeout_t	adasendorderedtag;
155 static void		adashutdown(void *arg, int howto);
156 
157 #ifndef ADA_DEFAULT_TIMEOUT
158 #define ADA_DEFAULT_TIMEOUT 30	/* Timeout in seconds */
159 #endif
160 
161 #ifndef	ADA_DEFAULT_RETRY
162 #define	ADA_DEFAULT_RETRY	4
163 #endif
164 
165 #ifndef	ADA_DEFAULT_SEND_ORDERED
166 #define	ADA_DEFAULT_SEND_ORDERED	1
167 #endif
168 
169 
170 static int ada_retry_count = ADA_DEFAULT_RETRY;
171 static int ada_default_timeout = ADA_DEFAULT_TIMEOUT;
172 static int ada_send_ordered = ADA_DEFAULT_SEND_ORDERED;
173 
174 SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD, 0,
175             "CAM Direct Access Disk driver");
176 SYSCTL_INT(_kern_cam_ada, OID_AUTO, retry_count, CTLFLAG_RW,
177            &ada_retry_count, 0, "Normal I/O retry count");
178 TUNABLE_INT("kern.cam.ada.retry_count", &ada_retry_count);
179 SYSCTL_INT(_kern_cam_ada, OID_AUTO, default_timeout, CTLFLAG_RW,
180            &ada_default_timeout, 0, "Normal I/O timeout (in seconds)");
181 TUNABLE_INT("kern.cam.ada.default_timeout", &ada_default_timeout);
182 SYSCTL_INT(_kern_cam_ada, OID_AUTO, ada_send_ordered, CTLFLAG_RW,
183            &ada_send_ordered, 0, "Send Ordered Tags");
184 TUNABLE_INT("kern.cam.ada.ada_send_ordered", &ada_send_ordered);
185 
186 /*
187  * ADA_ORDEREDTAG_INTERVAL determines how often, relative
188  * to the default timeout, we check to see whether an ordered
189  * tagged transaction is appropriate to prevent simple tag
190  * starvation.  Since we'd like to ensure that there is at least
191  * 1/2 of the timeout length left for a starved transaction to
192  * complete after we've sent an ordered tag, we must poll at least
193  * four times in every timeout period.  This takes care of the worst
194  * case where a starved transaction starts during an interval that
195  * meets the requirement "don't send an ordered tag" test so it takes
196  * us two intervals to determine that a tag must be sent.
197  */
198 #ifndef ADA_ORDEREDTAG_INTERVAL
199 #define ADA_ORDEREDTAG_INTERVAL 4
200 #endif
201 
202 static struct periph_driver adadriver =
203 {
204 	adainit, "ada",
205 	TAILQ_HEAD_INITIALIZER(adadriver.units), /* generation */ 0
206 };
207 
208 PERIPHDRIVER_DECLARE(ada, adadriver);
209 
210 MALLOC_DEFINE(M_ATADA, "ata_da", "ata_da buffers");
211 
212 static int
213 adaopen(struct disk *dp)
214 {
215 	struct cam_periph *periph;
216 	struct ada_softc *softc;
217 	int unit;
218 	int error;
219 
220 	periph = (struct cam_periph *)dp->d_drv1;
221 	if (periph == NULL) {
222 		return (ENXIO);
223 	}
224 
225 	if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
226 		return(ENXIO);
227 	}
228 
229 	cam_periph_lock(periph);
230 	if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
231 		cam_periph_unlock(periph);
232 		cam_periph_release(periph);
233 		return (error);
234 	}
235 
236 	unit = periph->unit_number;
237 	softc = (struct ada_softc *)periph->softc;
238 	softc->flags |= ADA_FLAG_OPEN;
239 
240 	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
241 	    ("adaopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit,
242 	     unit));
243 
244 	if ((softc->flags & ADA_FLAG_PACK_INVALID) != 0) {
245 		/* Invalidate our pack information. */
246 		softc->flags &= ~ADA_FLAG_PACK_INVALID;
247 	}
248 
249 	cam_periph_unhold(periph);
250 	cam_periph_unlock(periph);
251 	return (0);
252 }
253 
254 static int
255 adaclose(struct disk *dp)
256 {
257 	struct	cam_periph *periph;
258 	struct	ada_softc *softc;
259 	union ccb *ccb;
260 	int error;
261 
262 	periph = (struct cam_periph *)dp->d_drv1;
263 	if (periph == NULL)
264 		return (ENXIO);
265 
266 	cam_periph_lock(periph);
267 	if ((error = cam_periph_hold(periph, PRIBIO)) != 0) {
268 		cam_periph_unlock(periph);
269 		cam_periph_release(periph);
270 		return (error);
271 	}
272 
273 	softc = (struct ada_softc *)periph->softc;
274 	/* We only sync the cache if the drive is capable of it. */
275 	if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) {
276 
277 		ccb = cam_periph_getccb(periph, /*priority*/1);
278 		ccb->ccb_h.ccb_state = ADA_CCB_DUMP;
279 		cam_fill_ataio(&ccb->ataio,
280 				    1,
281 				    adadone,
282 				    CAM_DIR_NONE,
283 				    0,
284 				    NULL,
285 				    0,
286 				    ada_default_timeout*1000);
287 
288 		if (softc->flags & ADA_FLAG_CAN_48BIT)
289 			ata_48bit_cmd(&ccb->ataio, ATA_FLUSHCACHE48, 0, 0, 0);
290 		else
291 			ata_48bit_cmd(&ccb->ataio, ATA_FLUSHCACHE, 0, 0, 0);
292 		xpt_polled_action(ccb);
293 
294 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
295 			xpt_print(periph->path, "Synchronize cache failed\n");
296 
297 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
298 			cam_release_devq(ccb->ccb_h.path,
299 					 /*relsim_flags*/0,
300 					 /*reduction*/0,
301 					 /*timeout*/0,
302 					 /*getcount_only*/0);
303 		xpt_release_ccb(ccb);
304 	}
305 
306 	softc->flags &= ~ADA_FLAG_OPEN;
307 	cam_periph_unhold(periph);
308 	cam_periph_unlock(periph);
309 	cam_periph_release(periph);
310 	return (0);
311 }
312 
313 /*
314  * Actually translate the requested transfer into one the physical driver
315  * can understand.  The transfer is described by a buf and will include
316  * only one physical transfer.
317  */
318 static void
319 adastrategy(struct bio *bp)
320 {
321 	struct cam_periph *periph;
322 	struct ada_softc *softc;
323 
324 	periph = (struct cam_periph *)bp->bio_disk->d_drv1;
325 	if (periph == NULL) {
326 		biofinish(bp, NULL, ENXIO);
327 		return;
328 	}
329 	softc = (struct ada_softc *)periph->softc;
330 
331 	cam_periph_lock(periph);
332 
333 #if 0
334 	/*
335 	 * check it's not too big a transfer for our adapter
336 	 */
337 	scsi_minphys(bp,&sd_switch);
338 #endif
339 
340 	/*
341 	 * Mask interrupts so that the pack cannot be invalidated until
342 	 * after we are in the queue.  Otherwise, we might not properly
343 	 * clean up one of the buffers.
344 	 */
345 
346 	/*
347 	 * If the device has been made invalid, error out
348 	 */
349 	if ((softc->flags & ADA_FLAG_PACK_INVALID)) {
350 		cam_periph_unlock(periph);
351 		biofinish(bp, NULL, ENXIO);
352 		return;
353 	}
354 
355 	/*
356 	 * Place it in the queue of disk activities for this disk
357 	 */
358 	bioq_disksort(&softc->bio_queue, bp);
359 
360 	/*
361 	 * Schedule ourselves for performing the work.
362 	 */
363 	xpt_schedule(periph, /* XXX priority */1);
364 	cam_periph_unlock(periph);
365 
366 	return;
367 }
368 
369 static int
370 adadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
371 {
372 	struct	    cam_periph *periph;
373 	struct	    ada_softc *softc;
374 	u_int	    secsize;
375 	union	    ccb ccb;
376 	struct	    disk *dp;
377 	uint64_t    lba;
378 	uint16_t    count;
379 
380 	dp = arg;
381 	periph = dp->d_drv1;
382 	if (periph == NULL)
383 		return (ENXIO);
384 	softc = (struct ada_softc *)periph->softc;
385 	cam_periph_lock(periph);
386 	secsize = softc->params.secsize;
387 	lba = offset / secsize;
388 	count = length / secsize;
389 
390 	if ((softc->flags & ADA_FLAG_PACK_INVALID) != 0) {
391 		cam_periph_unlock(periph);
392 		return (ENXIO);
393 	}
394 
395 	if (length > 0) {
396 		periph->flags |= CAM_PERIPH_POLLED;
397 		xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1);
398 		ccb.ccb_h.ccb_state = ADA_CCB_DUMP;
399 		cam_fill_ataio(&ccb.ataio,
400 		    0,
401 		    adadone,
402 		    CAM_DIR_OUT,
403 		    0,
404 		    (u_int8_t *) virtual,
405 		    length,
406 		    ada_default_timeout*1000);
407 		if ((softc->flags & ADA_FLAG_CAN_48BIT) &&
408 		    (lba + count >= ATA_MAX_28BIT_LBA ||
409 		    count >= 256)) {
410 			ata_48bit_cmd(&ccb.ataio, ATA_WRITE_DMA48,
411 			    0, lba, count);
412 		} else {
413 			ata_36bit_cmd(&ccb.ataio, ATA_WRITE_DMA,
414 			    0, lba, count);
415 		}
416 		xpt_polled_action(&ccb);
417 
418 		if ((ccb.ataio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
419 			printf("Aborting dump due to I/O error.\n");
420 			cam_periph_unlock(periph);
421 			return(EIO);
422 		}
423 		cam_periph_unlock(periph);
424 		return(0);
425 	}
426 
427 	if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) {
428 		xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1);
429 
430 		ccb.ccb_h.ccb_state = ADA_CCB_DUMP;
431 		cam_fill_ataio(&ccb.ataio,
432 				    1,
433 				    adadone,
434 				    CAM_DIR_NONE,
435 				    0,
436 				    NULL,
437 				    0,
438 				    ada_default_timeout*1000);
439 
440 		if (softc->flags & ADA_FLAG_CAN_48BIT)
441 			ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE48, 0, 0, 0);
442 		else
443 			ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0);
444 		xpt_polled_action(&ccb);
445 
446 		if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
447 			xpt_print(periph->path, "Synchronize cache failed\n");
448 
449 		if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
450 			cam_release_devq(ccb.ccb_h.path,
451 					 /*relsim_flags*/0,
452 					 /*reduction*/0,
453 					 /*timeout*/0,
454 					 /*getcount_only*/0);
455 	}
456 	periph->flags &= ~CAM_PERIPH_POLLED;
457 	cam_periph_unlock(periph);
458 	return (0);
459 }
460 
461 static void
462 adainit(void)
463 {
464 	cam_status status;
465 
466 	/*
467 	 * Install a global async callback.  This callback will
468 	 * receive async callbacks like "new device found".
469 	 */
470 	status = xpt_register_async(AC_FOUND_DEVICE, adaasync, NULL, NULL);
471 
472 	if (status != CAM_REQ_CMP) {
473 		printf("ada: Failed to attach master async callback "
474 		       "due to status 0x%x!\n", status);
475 	} else if (ada_send_ordered) {
476 
477 		/* Register our shutdown event handler */
478 		if ((EVENTHANDLER_REGISTER(shutdown_post_sync, adashutdown,
479 					   NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
480 		    printf("adainit: shutdown event registration failed!\n");
481 	}
482 }
483 
484 static void
485 adaoninvalidate(struct cam_periph *periph)
486 {
487 	struct ada_softc *softc;
488 
489 	softc = (struct ada_softc *)periph->softc;
490 
491 	/*
492 	 * De-register any async callbacks.
493 	 */
494 	xpt_register_async(0, adaasync, periph, periph->path);
495 
496 	softc->flags |= ADA_FLAG_PACK_INVALID;
497 
498 	/*
499 	 * Return all queued I/O with ENXIO.
500 	 * XXX Handle any transactions queued to the card
501 	 *     with XPT_ABORT_CCB.
502 	 */
503 	bioq_flush(&softc->bio_queue, NULL, ENXIO);
504 
505 	disk_gone(softc->disk);
506 	xpt_print(periph->path, "lost device\n");
507 }
508 
509 static void
510 adacleanup(struct cam_periph *periph)
511 {
512 	struct ada_softc *softc;
513 
514 	softc = (struct ada_softc *)periph->softc;
515 
516 	xpt_print(periph->path, "removing device entry\n");
517 	cam_periph_unlock(periph);
518 
519 	/*
520 	 * If we can't free the sysctl tree, oh well...
521 	 */
522 	if ((softc->flags & ADA_FLAG_SCTX_INIT) != 0
523 	    && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
524 		xpt_print(periph->path, "can't remove sysctl context\n");
525 	}
526 
527 	disk_destroy(softc->disk);
528 	callout_drain(&softc->sendordered_c);
529 	free(softc, M_DEVBUF);
530 	cam_periph_lock(periph);
531 }
532 
533 static void
534 adaasync(void *callback_arg, u_int32_t code,
535 	struct cam_path *path, void *arg)
536 {
537 	struct cam_periph *periph;
538 
539 	periph = (struct cam_periph *)callback_arg;
540 	switch (code) {
541 	case AC_FOUND_DEVICE:
542 	{
543 		struct ccb_getdev *cgd;
544 		cam_status status;
545 
546 		cgd = (struct ccb_getdev *)arg;
547 		if (cgd == NULL)
548 			break;
549 
550 		if (cgd->protocol != PROTO_ATA)
551 			break;
552 
553 //		if (SID_TYPE(&cgd->inq_data) != T_DIRECT
554 //		    && SID_TYPE(&cgd->inq_data) != T_RBC
555 //		    && SID_TYPE(&cgd->inq_data) != T_OPTICAL)
556 //			break;
557 
558 		/*
559 		 * Allocate a peripheral instance for
560 		 * this device and start the probe
561 		 * process.
562 		 */
563 		status = cam_periph_alloc(adaregister, adaoninvalidate,
564 					  adacleanup, adastart,
565 					  "ada", CAM_PERIPH_BIO,
566 					  cgd->ccb_h.path, adaasync,
567 					  AC_FOUND_DEVICE, cgd);
568 
569 		if (status != CAM_REQ_CMP
570 		 && status != CAM_REQ_INPROG)
571 			printf("adaasync: Unable to attach to new device "
572 				"due to status 0x%x\n", status);
573 		break;
574 	}
575 	case AC_SENT_BDR:
576 	case AC_BUS_RESET:
577 	{
578 		struct ada_softc *softc;
579 		struct ccb_hdr *ccbh;
580 
581 		softc = (struct ada_softc *)periph->softc;
582 		/*
583 		 * Don't fail on the expected unit attention
584 		 * that will occur.
585 		 */
586 		softc->flags |= ADA_FLAG_RETRY_UA;
587 		LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
588 			ccbh->ccb_state |= ADA_CCB_RETRY_UA;
589 		/* FALLTHROUGH*/
590 	}
591 	default:
592 		cam_periph_async(periph, code, path, arg);
593 		break;
594 	}
595 }
596 
597 static void
598 adasysctlinit(void *context, int pending)
599 {
600 	struct cam_periph *periph;
601 	struct ada_softc *softc;
602 	char tmpstr[80], tmpstr2[80];
603 
604 	periph = (struct cam_periph *)context;
605 	if (cam_periph_acquire(periph) != CAM_REQ_CMP)
606 		return;
607 
608 	softc = (struct ada_softc *)periph->softc;
609 	snprintf(tmpstr, sizeof(tmpstr), "CAM ADA unit %d", periph->unit_number);
610 	snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
611 
612 	sysctl_ctx_init(&softc->sysctl_ctx);
613 	softc->flags |= ADA_FLAG_SCTX_INIT;
614 	softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
615 		SYSCTL_STATIC_CHILDREN(_kern_cam_ada), OID_AUTO, tmpstr2,
616 		CTLFLAG_RD, 0, tmpstr);
617 	if (softc->sysctl_tree == NULL) {
618 		printf("adasysctlinit: unable to allocate sysctl tree\n");
619 		cam_periph_release(periph);
620 		return;
621 	}
622 
623 	cam_periph_release(periph);
624 }
625 
626 static cam_status
627 adaregister(struct cam_periph *periph, void *arg)
628 {
629 	struct ada_softc *softc;
630 	struct ccb_pathinq cpi;
631 	struct ccb_getdev *cgd;
632 	char   announce_buf[80];
633 	struct disk_params *dp;
634 	caddr_t match;
635 	u_int maxio;
636 
637 	cgd = (struct ccb_getdev *)arg;
638 	if (periph == NULL) {
639 		printf("adaregister: periph was NULL!!\n");
640 		return(CAM_REQ_CMP_ERR);
641 	}
642 
643 	if (cgd == NULL) {
644 		printf("adaregister: no getdev CCB, can't register device\n");
645 		return(CAM_REQ_CMP_ERR);
646 	}
647 
648 	softc = (struct ada_softc *)malloc(sizeof(*softc), M_DEVBUF,
649 	    M_NOWAIT|M_ZERO);
650 
651 	if (softc == NULL) {
652 		printf("adaregister: Unable to probe new device. "
653 		       "Unable to allocate softc\n");
654 		return(CAM_REQ_CMP_ERR);
655 	}
656 
657 	LIST_INIT(&softc->pending_ccbs);
658 	softc->state = ADA_STATE_NORMAL;
659 	bioq_init(&softc->bio_queue);
660 
661 	if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48)
662 		softc->flags |= ADA_FLAG_CAN_48BIT;
663 	if (cgd->ident_data.support.command2 & ATA_SUPPORT_FLUSHCACHE)
664 		softc->flags |= ADA_FLAG_CAN_FLUSHCACHE;
665 	if (cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ &&
666 	    cgd->ident_data.queue >= 31)
667 		softc->flags |= ADA_FLAG_CAN_NCQ;
668 //	if ((cgd->inq_data.flags & SID_CmdQue) != 0)
669 //		softc->flags |= ADA_FLAG_TAGGED_QUEUING;
670 
671 	periph->softc = softc;
672 
673 	/*
674 	 * See if this device has any quirks.
675 	 */
676 //	match = cam_quirkmatch((caddr_t)&cgd->inq_data,
677 //			       (caddr_t)ada_quirk_table,
678 //			       sizeof(ada_quirk_table)/sizeof(*ada_quirk_table),
679 //			       sizeof(*ada_quirk_table), scsi_inquiry_match);
680 	match = NULL;
681 
682 	if (match != NULL)
683 		softc->quirks = ((struct ada_quirk_entry *)match)->quirks;
684 	else
685 		softc->quirks = ADA_Q_NONE;
686 
687 	/* Check if the SIM does not want queued commands */
688 	bzero(&cpi, sizeof(cpi));
689 	xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1);
690 	cpi.ccb_h.func_code = XPT_PATH_INQ;
691 	xpt_action((union ccb *)&cpi);
692 	if (cpi.ccb_h.status != CAM_REQ_CMP ||
693 	    (cpi.hba_inquiry & PI_TAG_ABLE) == 0)
694 		softc->flags &= ~ADA_FLAG_CAN_NCQ;
695 
696 	TASK_INIT(&softc->sysctl_task, 0, adasysctlinit, periph);
697 
698 	/*
699 	 * Register this media as a disk
700 	 */
701 	mtx_unlock(periph->sim->mtx);
702 	softc->disk = disk_alloc();
703 	softc->disk->d_open = adaopen;
704 	softc->disk->d_close = adaclose;
705 	softc->disk->d_strategy = adastrategy;
706 	softc->disk->d_dump = adadump;
707 	softc->disk->d_name = "ada";
708 	softc->disk->d_drv1 = periph;
709 	maxio = cpi.maxio;		/* Honor max I/O size of SIM */
710 	if (maxio == 0)
711 		maxio = DFLTPHYS;	/* traditional default */
712 	else if (maxio > MAXPHYS)
713 		maxio = MAXPHYS;	/* for safety */
714 	if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48)
715 		maxio = min(maxio, 65535 * 512);
716 	else					/* 28bit ATA command limit */
717 		maxio = min(maxio, 255 * 512);
718 	softc->disk->d_maxsize = maxio;
719 	softc->disk->d_unit = periph->unit_number;
720 	softc->disk->d_flags = 0;
721 	if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE)
722 		softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
723 
724 	adasetgeom(periph, cgd);
725 	softc->disk->d_sectorsize = softc->params.secsize;
726 	softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
727 	/* XXX: these are not actually "firmware" values, so they may be wrong */
728 	softc->disk->d_fwsectors = softc->params.secs_per_track;
729 	softc->disk->d_fwheads = softc->params.heads;
730 //	softc->disk->d_devstat->block_size = softc->params.secsize;
731 //	softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE;
732 
733 	disk_create(softc->disk, DISK_VERSION);
734 	mtx_lock(periph->sim->mtx);
735 
736 	dp = &softc->params;
737 	snprintf(announce_buf, sizeof(announce_buf),
738 		"%juMB (%ju %u byte sectors: %dH %dS/T %dC)",
739 		(uintmax_t)(((uintmax_t)dp->secsize *
740 		dp->sectors) / (1024*1024)),
741 		(uintmax_t)dp->sectors,
742 		dp->secsize, dp->heads,
743 		dp->secs_per_track, dp->cylinders);
744 	xpt_announce_periph(periph, announce_buf);
745 	if (softc->flags & ADA_FLAG_CAN_NCQ) {
746 		printf("%s%d: Native Command Queueing enabled\n",
747 		       periph->periph_name, periph->unit_number);
748 	}
749 
750 	/*
751 	 * Add async callbacks for bus reset and
752 	 * bus device reset calls.  I don't bother
753 	 * checking if this fails as, in most cases,
754 	 * the system will function just fine without
755 	 * them and the only alternative would be to
756 	 * not attach the device on failure.
757 	 */
758 	xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
759 			   adaasync, periph, periph->path);
760 
761 	/*
762 	 * Take an exclusive refcount on the periph while adastart is called
763 	 * to finish the probe.  The reference will be dropped in adadone at
764 	 * the end of probe.
765 	 */
766 //	(void)cam_periph_hold(periph, PRIBIO);
767 //	xpt_schedule(periph, /*priority*/5);
768 
769 	/*
770 	 * Schedule a periodic event to occasionally send an
771 	 * ordered tag to a device.
772 	 */
773 	callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0);
774 	callout_reset(&softc->sendordered_c,
775 	    (ADA_DEFAULT_TIMEOUT * hz) / ADA_ORDEREDTAG_INTERVAL,
776 	    adasendorderedtag, softc);
777 
778 	return(CAM_REQ_CMP);
779 }
780 
781 static void
782 adastart(struct cam_periph *periph, union ccb *start_ccb)
783 {
784 	struct ada_softc *softc;
785 
786 	softc = (struct ada_softc *)periph->softc;
787 
788 	switch (softc->state) {
789 	case ADA_STATE_NORMAL:
790 	{
791 		/* Pull a buffer from the queue and get going on it */
792 		struct bio *bp;
793 
794 		/*
795 		 * See if there is a buf with work for us to do..
796 		 */
797 		bp = bioq_first(&softc->bio_queue);
798 		if (periph->immediate_priority <= periph->pinfo.priority) {
799 			CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
800 					("queuing for immediate ccb\n"));
801 			start_ccb->ccb_h.ccb_state = ADA_CCB_WAITING;
802 			SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
803 					  periph_links.sle);
804 			periph->immediate_priority = CAM_PRIORITY_NONE;
805 			wakeup(&periph->ccb_list);
806 		} else if (bp == NULL) {
807 			xpt_release_ccb(start_ccb);
808 		} else {
809 			struct ccb_ataio *ataio = &start_ccb->ataio;
810 			u_int8_t tag_code;
811 
812 			bioq_remove(&softc->bio_queue, bp);
813 
814 			if ((softc->flags & ADA_FLAG_NEED_OTAG) != 0) {
815 				softc->flags &= ~ADA_FLAG_NEED_OTAG;
816 				softc->ordered_tag_count++;
817 				tag_code = 0;//MSG_ORDERED_Q_TAG;
818 			} else {
819 				tag_code = 0;//MSG_SIMPLE_Q_TAG;
820 			}
821 			switch (bp->bio_cmd) {
822 			case BIO_READ:
823 			case BIO_WRITE:
824 			{
825 				uint64_t lba = bp->bio_pblkno;
826 				uint16_t count = bp->bio_bcount / softc->params.secsize;
827 
828 				cam_fill_ataio(ataio,
829 				    ada_retry_count,
830 				    adadone,
831 				    bp->bio_cmd == BIO_READ ?
832 				        CAM_DIR_IN : CAM_DIR_OUT,
833 				    tag_code,
834 				    bp->bio_data,
835 				    bp->bio_bcount,
836 				    ada_default_timeout*1000);
837 
838 				if (softc->flags & ADA_FLAG_CAN_NCQ) {
839 					if (bp->bio_cmd == BIO_READ) {
840 						ata_ncq_cmd(ataio, ATA_READ_FPDMA_QUEUED,
841 						    lba, count);
842 					} else {
843 						ata_ncq_cmd(ataio, ATA_WRITE_FPDMA_QUEUED,
844 						    lba, count);
845 					}
846 				} else if ((softc->flags & ADA_FLAG_CAN_48BIT) &&
847 				    (lba + count >= ATA_MAX_28BIT_LBA ||
848 				    count >= 256)) {
849 					if (bp->bio_cmd == BIO_READ) {
850 						ata_48bit_cmd(ataio, ATA_READ_DMA48,
851 						    0, lba, count);
852 					} else {
853 						ata_48bit_cmd(ataio, ATA_WRITE_DMA48,
854 						    0, lba, count);
855 					}
856 				} else {
857 					if (bp->bio_cmd == BIO_READ) {
858 						ata_36bit_cmd(ataio, ATA_READ_DMA,
859 						    0, lba, count);
860 					} else {
861 						ata_36bit_cmd(ataio, ATA_WRITE_DMA,
862 						    0, lba, count);
863 					}
864 				}
865 			}
866 				break;
867 			case BIO_FLUSH:
868 				cam_fill_ataio(ataio,
869 				    1,
870 				    adadone,
871 				    CAM_DIR_NONE,
872 				    tag_code,
873 				    NULL,
874 				    0,
875 				    ada_default_timeout*1000);
876 
877 				if (softc->flags & ADA_FLAG_CAN_48BIT)
878 					ata_48bit_cmd(ataio, ATA_FLUSHCACHE48, 0, 0, 0);
879 				else
880 					ata_48bit_cmd(ataio, ATA_FLUSHCACHE, 0, 0, 0);
881 				break;
882 			}
883 			start_ccb->ccb_h.ccb_state = ADA_CCB_BUFFER_IO;
884 
885 			/*
886 			 * Block out any asyncronous callbacks
887 			 * while we touch the pending ccb list.
888 			 */
889 			LIST_INSERT_HEAD(&softc->pending_ccbs,
890 					 &start_ccb->ccb_h, periph_links.le);
891 			softc->outstanding_cmds++;
892 
893 			/* We expect a unit attention from this device */
894 			if ((softc->flags & ADA_FLAG_RETRY_UA) != 0) {
895 				start_ccb->ccb_h.ccb_state |= ADA_CCB_RETRY_UA;
896 				softc->flags &= ~ADA_FLAG_RETRY_UA;
897 			}
898 
899 			start_ccb->ccb_h.ccb_bp = bp;
900 			bp = bioq_first(&softc->bio_queue);
901 
902 			xpt_action(start_ccb);
903 		}
904 
905 		if (bp != NULL) {
906 			/* Have more work to do, so ensure we stay scheduled */
907 			xpt_schedule(periph, /* XXX priority */1);
908 		}
909 		break;
910 	}
911 	}
912 }
913 
914 static void
915 adadone(struct cam_periph *periph, union ccb *done_ccb)
916 {
917 	struct ada_softc *softc;
918 	struct ccb_ataio *ataio;
919 
920 	softc = (struct ada_softc *)periph->softc;
921 	ataio = &done_ccb->ataio;
922 	switch (ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) {
923 	case ADA_CCB_BUFFER_IO:
924 	{
925 		struct bio *bp;
926 
927 		bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
928 		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
929 			int error;
930 
931 			error = adaerror(done_ccb, CAM_RETRY_SELTO, 0);
932 			if (error == ERESTART) {
933 				/*
934 				 * A retry was scheuled, so
935 				 * just return.
936 				 */
937 				return;
938 			}
939 			if (error != 0) {
940 
941 				if (error == ENXIO) {
942 					/*
943 					 * Catastrophic error.  Mark our pack as
944 					 * invalid.
945 					 */
946 					/*
947 					 * XXX See if this is really a media
948 					 * XXX change first?
949 					 */
950 					xpt_print(periph->path,
951 					    "Invalidating pack\n");
952 					softc->flags |= ADA_FLAG_PACK_INVALID;
953 				}
954 
955 				/*
956 				 * return all queued I/O with EIO, so that
957 				 * the client can retry these I/Os in the
958 				 * proper order should it attempt to recover.
959 				 */
960 				bioq_flush(&softc->bio_queue, NULL, EIO);
961 				bp->bio_error = error;
962 				bp->bio_resid = bp->bio_bcount;
963 				bp->bio_flags |= BIO_ERROR;
964 			} else {
965 				bp->bio_resid = ataio->resid;
966 				bp->bio_error = 0;
967 				if (bp->bio_resid != 0)
968 					bp->bio_flags |= BIO_ERROR;
969 			}
970 			if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
971 				cam_release_devq(done_ccb->ccb_h.path,
972 						 /*relsim_flags*/0,
973 						 /*reduction*/0,
974 						 /*timeout*/0,
975 						 /*getcount_only*/0);
976 		} else {
977 			if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
978 				panic("REQ_CMP with QFRZN");
979 			bp->bio_resid = ataio->resid;
980 			if (ataio->resid > 0)
981 				bp->bio_flags |= BIO_ERROR;
982 		}
983 
984 		/*
985 		 * Block out any asyncronous callbacks
986 		 * while we touch the pending ccb list.
987 		 */
988 		LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
989 		softc->outstanding_cmds--;
990 		if (softc->outstanding_cmds == 0)
991 			softc->flags |= ADA_FLAG_WENT_IDLE;
992 
993 		biodone(bp);
994 		break;
995 	}
996 	case ADA_CCB_WAITING:
997 	{
998 		/* Caller will release the CCB */
999 		wakeup(&done_ccb->ccb_h.cbfcnp);
1000 		return;
1001 	}
1002 	case ADA_CCB_DUMP:
1003 		/* No-op.  We're polling */
1004 		return;
1005 	default:
1006 		break;
1007 	}
1008 	xpt_release_ccb(done_ccb);
1009 }
1010 
1011 static int
1012 adaerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
1013 {
1014 	struct ada_softc	  *softc;
1015 	struct cam_periph *periph;
1016 
1017 	periph = xpt_path_periph(ccb->ccb_h.path);
1018 	softc = (struct ada_softc *)periph->softc;
1019 
1020 	return(cam_periph_error(ccb, cam_flags, sense_flags,
1021 				&softc->saved_ccb));
1022 }
1023 
1024 static void
1025 adasetgeom(struct cam_periph *periph, struct ccb_getdev *cgd)
1026 {
1027 	struct ada_softc *softc = (struct ada_softc *)periph->softc;
1028 	struct disk_params *dp = &softc->params;
1029 	u_int64_t lbasize48;
1030 	u_int32_t lbasize;
1031 
1032 	dp->secsize = 512;
1033 	if ((cgd->ident_data.atavalid & ATA_FLAG_54_58) &&
1034 		cgd->ident_data.current_heads && cgd->ident_data.current_sectors) {
1035 		dp->heads = cgd->ident_data.current_heads;
1036 		dp->secs_per_track = cgd->ident_data.current_sectors;
1037 		dp->cylinders = cgd->ident_data.cylinders;
1038 		dp->sectors = (u_int32_t)cgd->ident_data.current_size_1 |
1039 			  ((u_int32_t)cgd->ident_data.current_size_2 << 16);
1040 	} else {
1041 		dp->heads = cgd->ident_data.heads;
1042 		dp->secs_per_track = cgd->ident_data.sectors;
1043 		dp->cylinders = cgd->ident_data.cylinders;
1044 		dp->sectors = cgd->ident_data.cylinders * dp->heads * dp->secs_per_track;
1045 	}
1046 	lbasize = (u_int32_t)cgd->ident_data.lba_size_1 |
1047 		  ((u_int32_t)cgd->ident_data.lba_size_2 << 16);
1048 
1049     /* does this device need oldstyle CHS addressing */
1050 //    if (!ad_version(cgd->ident_data.version_major) || !lbasize)
1051 //	atadev->flags |= ATA_D_USE_CHS;
1052 
1053 	/* use the 28bit LBA size if valid or bigger than the CHS mapping */
1054 	if (cgd->ident_data.cylinders == 16383 || dp->sectors < lbasize)
1055 		dp->sectors = lbasize;
1056 
1057 	/* use the 48bit LBA size if valid */
1058 	lbasize48 = ((u_int64_t)cgd->ident_data.lba_size48_1) |
1059 		    ((u_int64_t)cgd->ident_data.lba_size48_2 << 16) |
1060 		    ((u_int64_t)cgd->ident_data.lba_size48_3 << 32) |
1061 		    ((u_int64_t)cgd->ident_data.lba_size48_4 << 48);
1062 	if ((cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) &&
1063 	    lbasize48 > ATA_MAX_28BIT_LBA)
1064 		dp->sectors = lbasize48;
1065 }
1066 
1067 static void
1068 adasendorderedtag(void *arg)
1069 {
1070 	struct ada_softc *softc = arg;
1071 
1072 	if (ada_send_ordered) {
1073 		if ((softc->ordered_tag_count == 0)
1074 		 && ((softc->flags & ADA_FLAG_WENT_IDLE) == 0)) {
1075 			softc->flags |= ADA_FLAG_NEED_OTAG;
1076 		}
1077 		if (softc->outstanding_cmds > 0)
1078 			softc->flags &= ~ADA_FLAG_WENT_IDLE;
1079 
1080 		softc->ordered_tag_count = 0;
1081 	}
1082 	/* Queue us up again */
1083 	callout_reset(&softc->sendordered_c,
1084 	    (ADA_DEFAULT_TIMEOUT * hz) / ADA_ORDEREDTAG_INTERVAL,
1085 	    adasendorderedtag, softc);
1086 }
1087 
1088 /*
1089  * Step through all ADA peripheral drivers, and if the device is still open,
1090  * sync the disk cache to physical media.
1091  */
1092 static void
1093 adashutdown(void * arg, int howto)
1094 {
1095 	struct cam_periph *periph;
1096 	struct ada_softc *softc;
1097 
1098 	TAILQ_FOREACH(periph, &adadriver.units, unit_links) {
1099 		union ccb ccb;
1100 
1101 		cam_periph_lock(periph);
1102 		softc = (struct ada_softc *)periph->softc;
1103 		/*
1104 		 * We only sync the cache if the drive is still open, and
1105 		 * if the drive is capable of it..
1106 		 */
1107 		if (((softc->flags & ADA_FLAG_OPEN) == 0) ||
1108 		    (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) == 0) {
1109 			cam_periph_unlock(periph);
1110 			continue;
1111 		}
1112 
1113 		xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1);
1114 
1115 		ccb.ccb_h.ccb_state = ADA_CCB_DUMP;
1116 		cam_fill_ataio(&ccb.ataio,
1117 				    1,
1118 				    adadone,
1119 				    CAM_DIR_NONE,
1120 				    0,
1121 				    NULL,
1122 				    0,
1123 				    ada_default_timeout*1000);
1124 
1125 		if (softc->flags & ADA_FLAG_CAN_48BIT)
1126 			ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE48, 0, 0, 0);
1127 		else
1128 			ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0);
1129 		xpt_polled_action(&ccb);
1130 
1131 		if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
1132 			xpt_print(periph->path, "Synchronize cache failed\n");
1133 
1134 		if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
1135 			cam_release_devq(ccb.ccb_h.path,
1136 					 /*relsim_flags*/0,
1137 					 /*reduction*/0,
1138 					 /*timeout*/0,
1139 					 /*getcount_only*/0);
1140 		cam_periph_unlock(periph);
1141 	}
1142 }
1143 
1144 #endif /* _KERNEL */
1145