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