1507c3241Smlf /*
2507c3241Smlf  * CDDL HEADER START
3507c3241Smlf  *
4507c3241Smlf  * The contents of this file are subject to the terms of the
5ae115bc7Smrj  * Common Development and Distribution License (the "License").
6507c3241Smlf  * You may not use this file except in compliance with the License.
7507c3241Smlf  *
8507c3241Smlf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9507c3241Smlf  * or http://www.opensolaris.org/os/licensing.
10507c3241Smlf  * See the License for the specific language governing permissions
11507c3241Smlf  * and limitations under the License.
12507c3241Smlf  *
13507c3241Smlf  * When distributing Covered Code, include this CDDL HEADER in each
14507c3241Smlf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15507c3241Smlf  * If applicable, add the following below this CDDL HEADER, with the
16507c3241Smlf  * fields enclosed by brackets "[]" replaced with your own identifying
17507c3241Smlf  * information: Portions Copyright [yyyy] [name of copyright owner]
18507c3241Smlf  *
19507c3241Smlf  * CDDL HEADER END
20507c3241Smlf  */
21507c3241Smlf 
22507c3241Smlf /*
230f1b305eSSeth Goldberg  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24507c3241Smlf  * Use is subject to license terms.
25*89b43686SBayard Bell  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
26507c3241Smlf  */
27507c3241Smlf 
28507c3241Smlf 
29507c3241Smlf #include <sys/types.h>
30507c3241Smlf 
31507c3241Smlf #include "ata_common.h"
32507c3241Smlf #include "atapi.h"
33507c3241Smlf 
34507c3241Smlf /* SCSA entry points */
35507c3241Smlf 
36507c3241Smlf static int atapi_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
37507c3241Smlf     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
38507c3241Smlf static int atapi_tran_tgt_probe(struct scsi_device *sd, int (*callback)(void));
39507c3241Smlf static void atapi_tran_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
40507c3241Smlf     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
41507c3241Smlf static int atapi_tran_abort(struct scsi_address *ap, struct scsi_pkt *spktp);
42507c3241Smlf static int atapi_tran_reset(struct scsi_address *ap, int level);
43507c3241Smlf static int atapi_tran_getcap(struct scsi_address *ap, char *capstr, int whom);
44507c3241Smlf static int atapi_tran_setcap(struct scsi_address *ap, char *capstr,
45507c3241Smlf     int value, int whom);
46507c3241Smlf static struct scsi_pkt	*atapi_tran_init_pkt(struct scsi_address *ap,
47507c3241Smlf     struct scsi_pkt *spktp, struct buf *bp, int cmdlen, int statuslen,
48507c3241Smlf     int tgtlen, int flags, int (*callback)(caddr_t), caddr_t arg);
49507c3241Smlf static void atapi_tran_destroy_pkt(struct scsi_address *ap,
50507c3241Smlf     struct scsi_pkt *spktp);
51507c3241Smlf static void atapi_tran_dmafree(struct scsi_address *ap, struct scsi_pkt *spktp);
52507c3241Smlf static void atapi_tran_sync_pkt(struct scsi_address *ap,
53507c3241Smlf     struct scsi_pkt *spktp);
54507c3241Smlf static int atapi_tran_start(struct scsi_address *ap, struct scsi_pkt *spktp);
55507c3241Smlf 
56507c3241Smlf /*
57507c3241Smlf  * packet callbacks
58507c3241Smlf  */
59507c3241Smlf static void atapi_complete(ata_drv_t *ata_drvp, ata_pkt_t *ata_pktp,
60507c3241Smlf     int do_callback);
61507c3241Smlf static int atapi_id_update(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
62507c3241Smlf     ata_pkt_t *ata_pktp);
63507c3241Smlf 
64507c3241Smlf /*
65507c3241Smlf  * Local static data
66507c3241Smlf  */
67507c3241Smlf 
68507c3241Smlf #if 0
69507c3241Smlf static ddi_dma_lim_t atapi_dma_limits = {
70507c3241Smlf 	0,		/* address low				*/
71507c3241Smlf 	0xffffffffU,	/* address high				*/
72507c3241Smlf 	0,		/* counter max				*/
73507c3241Smlf 	1,		/* burstsize				*/
74507c3241Smlf 	DMA_UNIT_8,	/* minimum xfer				*/
75507c3241Smlf 	0,		/* dma speed				*/
76507c3241Smlf 	(uint_t)DMALIM_VER0,	/* version			*/
77507c3241Smlf 	0xffffffffU,	/* address register			*/
78507c3241Smlf 	0xffffffffU,	/* counter register			*/
79507c3241Smlf 	1,		/* granular				*/
80507c3241Smlf 	1,		/* scatter/gather list length		*/
81507c3241Smlf 	0xffffffffU	/* request size				*/
82507c3241Smlf };
83507c3241Smlf #endif
84507c3241Smlf 
85507c3241Smlf static	int	atapi_use_static_geometry = TRUE;
86507c3241Smlf static	int	atapi_arq_enable = TRUE;
87507c3241Smlf 
88507c3241Smlf 
89507c3241Smlf /*
90507c3241Smlf  *
91507c3241Smlf  * Call SCSA init to initialize the ATAPI half of the driver
92507c3241Smlf  *
93507c3241Smlf  */
94507c3241Smlf 
95507c3241Smlf int
atapi_attach(ata_ctl_t * ata_ctlp)96507c3241Smlf atapi_attach(ata_ctl_t *ata_ctlp)
97507c3241Smlf {
98507c3241Smlf 	dev_info_t	*dip = ata_ctlp->ac_dip;
99507c3241Smlf 	scsi_hba_tran_t *tran;
100507c3241Smlf 
101507c3241Smlf 	ADBG_TRACE(("atapi_init entered\n"));
102507c3241Smlf 
103507c3241Smlf 	/* allocate transport structure */
104507c3241Smlf 
105507c3241Smlf 	tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP);
106507c3241Smlf 
107507c3241Smlf 	if (tran == NULL) {
108507c3241Smlf 		ADBG_WARN(("atapi_init: scsi_hba_tran_alloc failed\n"));
109507c3241Smlf 		goto errout;
110507c3241Smlf 	}
111507c3241Smlf 
112507c3241Smlf 	ata_ctlp->ac_atapi_tran = tran;
113507c3241Smlf 	ata_ctlp->ac_flags |= AC_SCSI_HBA_TRAN_ALLOC;
114507c3241Smlf 
115507c3241Smlf 	/* initialize transport structure */
116507c3241Smlf 
117507c3241Smlf 	tran->tran_hba_private = ata_ctlp;
118507c3241Smlf 	tran->tran_tgt_private = NULL;
119507c3241Smlf 
120507c3241Smlf 	tran->tran_tgt_init = atapi_tran_tgt_init;
121507c3241Smlf 	tran->tran_tgt_probe = atapi_tran_tgt_probe;
122507c3241Smlf 	tran->tran_tgt_free = atapi_tran_tgt_free;
123507c3241Smlf 	tran->tran_start = atapi_tran_start;
124507c3241Smlf 	tran->tran_reset = atapi_tran_reset;
125507c3241Smlf 	tran->tran_abort = atapi_tran_abort;
126507c3241Smlf 	tran->tran_getcap = atapi_tran_getcap;
127507c3241Smlf 	tran->tran_setcap = atapi_tran_setcap;
128507c3241Smlf 	tran->tran_init_pkt = atapi_tran_init_pkt;
129507c3241Smlf 	tran->tran_destroy_pkt = atapi_tran_destroy_pkt;
130507c3241Smlf 	tran->tran_dmafree = atapi_tran_dmafree;
131507c3241Smlf 	tran->tran_sync_pkt = atapi_tran_sync_pkt;
132507c3241Smlf 
133507c3241Smlf 	if (scsi_hba_attach_setup(ata_ctlp->ac_dip, &ata_pciide_dma_attr, tran,
1346fd12ef3Slh 	    SCSI_HBA_TRAN_CLONE) != DDI_SUCCESS) {
135507c3241Smlf 		ADBG_WARN(("atapi_init: scsi_hba_attach_setup failed\n"));
136507c3241Smlf 		goto errout;
137507c3241Smlf 	}
138507c3241Smlf 
139507c3241Smlf 	ata_ctlp->ac_flags |= AC_SCSI_HBA_ATTACH;
140507c3241Smlf 
141507c3241Smlf 	return (TRUE);
142507c3241Smlf 
143507c3241Smlf errout:
144507c3241Smlf 	atapi_detach(ata_ctlp);
145507c3241Smlf 	return (FALSE);
146507c3241Smlf }
147507c3241Smlf 
148507c3241Smlf 
149507c3241Smlf /*
150507c3241Smlf  *
151507c3241Smlf  * destroy the atapi sub-system
152507c3241Smlf  *
153507c3241Smlf  */
154507c3241Smlf 
155507c3241Smlf void
atapi_detach(ata_ctl_t * ata_ctlp)156507c3241Smlf atapi_detach(
157507c3241Smlf 	ata_ctl_t *ata_ctlp)
158507c3241Smlf {
159507c3241Smlf 	ADBG_TRACE(("atapi_detach entered\n"));
160507c3241Smlf 
161507c3241Smlf 	if (ata_ctlp->ac_flags & AC_SCSI_HBA_ATTACH)
162ae115bc7Smrj 		(void) scsi_hba_detach(ata_ctlp->ac_dip);
163507c3241Smlf 
164507c3241Smlf 	if (ata_ctlp->ac_flags & AC_SCSI_HBA_TRAN_ALLOC)
165507c3241Smlf 		scsi_hba_tran_free(ata_ctlp->ac_atapi_tran);
166507c3241Smlf }
167507c3241Smlf 
168507c3241Smlf 
169507c3241Smlf 
170507c3241Smlf /*
171507c3241Smlf  *
172507c3241Smlf  * initialize the ATAPI drive's soft-state based on the
173507c3241Smlf  * response to IDENTIFY PACKET DEVICE command
174507c3241Smlf  *
175507c3241Smlf  */
176507c3241Smlf 
177507c3241Smlf int
atapi_init_drive(ata_drv_t * ata_drvp)178507c3241Smlf atapi_init_drive(
179507c3241Smlf 	ata_drv_t *ata_drvp)
180507c3241Smlf {
181c8531848Syt 	ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
182c8531848Syt 
183507c3241Smlf 	ADBG_TRACE(("atapi_init_drive entered\n"));
184507c3241Smlf 
185507c3241Smlf 	/* Determine ATAPI CDB size */
18662c8caf3SAda 	(void) atapi_id_update(ata_ctlp, ata_drvp, NULL);
187507c3241Smlf 
188507c3241Smlf 	switch (ata_drvp->ad_id.ai_config & ATAPI_ID_CFG_PKT_SZ) {
189507c3241Smlf 
190507c3241Smlf 	case ATAPI_ID_CFG_PKT_12B:
191507c3241Smlf 		ata_drvp->ad_cdb_len = 12;
192507c3241Smlf 		break;
193507c3241Smlf 	case ATAPI_ID_CFG_PKT_16B:
194507c3241Smlf 		ata_drvp->ad_cdb_len = 16;
195507c3241Smlf 		break;
196507c3241Smlf 	default:
197507c3241Smlf 		ADBG_WARN(("atapi_init_drive: bad pkt size support\n"));
198507c3241Smlf 		return (FALSE);
199507c3241Smlf 	}
200507c3241Smlf 
201507c3241Smlf 	/* determine if drive gives an intr when it wants the CDB */
202507c3241Smlf 
203507c3241Smlf 	if ((ata_drvp->ad_id.ai_config & ATAPI_ID_CFG_DRQ_TYPE) !=
204507c3241Smlf 	    ATAPI_ID_CFG_DRQ_INTR)
205507c3241Smlf 		ata_drvp->ad_flags |= AD_NO_CDB_INTR;
206507c3241Smlf 
207c8531848Syt 	/*
208c8531848Syt 	 * Some devices may have no DMA mode enabled (UDMA or MWDMA)
209c8531848Syt 	 * by default, so here we need check and enable DMA if none
210c8531848Syt 	 * mode is selected.
211c8531848Syt 	 */
212c8531848Syt 	if (ata_set_dma_mode(ata_ctlp, ata_drvp) == TRUE) {
213c8531848Syt 		/* Update the IDENTIFY PACKET DEVICE data */
214c8531848Syt 		(void) atapi_id_update(ata_ctlp, ata_drvp, NULL);
215c8531848Syt 	}
216c8531848Syt 
217507c3241Smlf 	return (TRUE);
218507c3241Smlf }
219507c3241Smlf 
220507c3241Smlf 
221507c3241Smlf /*
222507c3241Smlf  *
223507c3241Smlf  * destroy an atapi drive
224507c3241Smlf  *
225507c3241Smlf  */
226507c3241Smlf 
227507c3241Smlf /* ARGSUSED */
228507c3241Smlf void
atapi_uninit_drive(ata_drv_t * ata_drvp)229507c3241Smlf atapi_uninit_drive(
230507c3241Smlf 	ata_drv_t *ata_drvp)
231507c3241Smlf {
232507c3241Smlf 	ADBG_TRACE(("atapi_uninit_drive entered\n"));
233507c3241Smlf }
234507c3241Smlf 
235507c3241Smlf /*
236507c3241Smlf  *
237507c3241Smlf  * Issue an IDENTIFY PACKET (ATAPI) DEVICE command
238507c3241Smlf  *
239507c3241Smlf  */
240507c3241Smlf 
241507c3241Smlf int
atapi_id(ddi_acc_handle_t io_hdl1,caddr_t ioaddr1,ddi_acc_handle_t io_hdl2,caddr_t ioaddr2,struct ata_id * ata_idp)242507c3241Smlf atapi_id(
243507c3241Smlf 	ddi_acc_handle_t io_hdl1,
244507c3241Smlf 	caddr_t		 ioaddr1,
245507c3241Smlf 	ddi_acc_handle_t io_hdl2,
246507c3241Smlf 	caddr_t		 ioaddr2,
247507c3241Smlf 	struct ata_id	*ata_idp)
248507c3241Smlf {
249507c3241Smlf 	int	rc;
250507c3241Smlf 
251507c3241Smlf 	ADBG_TRACE(("atapi_id entered\n"));
252507c3241Smlf 
253507c3241Smlf 	rc = ata_id_common(ATC_ID_PACKET_DEVICE, FALSE, io_hdl1, ioaddr1,
2546fd12ef3Slh 	    io_hdl2, ioaddr2, ata_idp);
255507c3241Smlf 
256507c3241Smlf 	if (!rc)
257507c3241Smlf 		return (FALSE);
258507c3241Smlf 
259507c3241Smlf 	if ((ata_idp->ai_config & ATAC_ATAPI_TYPE_MASK) != ATAC_ATAPI_TYPE)
260507c3241Smlf 		return (FALSE);
261507c3241Smlf 
262507c3241Smlf 	return (TRUE);
263507c3241Smlf }
264507c3241Smlf 
265507c3241Smlf 
266507c3241Smlf /*
267507c3241Smlf  *
268507c3241Smlf  * Check the device's register block for the ATAPI signature.
269507c3241Smlf  *
270507c3241Smlf  * Although the spec says the sector count, sector number and device/head
271507c3241Smlf  * registers are also part of the signature, for some unknown reason, this
272507c3241Smlf  * routine only checks the cyl hi and cyl low registers. I'm just
273507c3241Smlf  * guessing, but it might be because ATA and ATAPI devices return
274507c3241Smlf  * identical values in those registers and we actually rely on the
275507c3241Smlf  * IDENTIFY DEVICE and IDENTIFY PACKET DEVICE commands to recognize the
276507c3241Smlf  * device type.
277507c3241Smlf  *
278507c3241Smlf  */
279507c3241Smlf 
280507c3241Smlf int
atapi_signature(ddi_acc_handle_t io_hdl,caddr_t ioaddr)281507c3241Smlf atapi_signature(
282507c3241Smlf 	ddi_acc_handle_t io_hdl,
283507c3241Smlf 	caddr_t ioaddr)
284507c3241Smlf {
285507c3241Smlf 	int	rc = FALSE;
286507c3241Smlf 	ADBG_TRACE(("atapi_signature entered\n"));
287507c3241Smlf 
288507c3241Smlf 	if (ddi_get8(io_hdl, (uchar_t *)ioaddr + AT_HCYL) == ATAPI_SIG_HI &&
2896fd12ef3Slh 	    ddi_get8(io_hdl, (uchar_t *)ioaddr + AT_LCYL) != ATAPI_SIG_LO)
290507c3241Smlf 		rc = TRUE;
291507c3241Smlf 
292507c3241Smlf 	/*
293507c3241Smlf 	 * The following is a little bit of bullet proofing.
294507c3241Smlf 	 *
295507c3241Smlf 	 * When some drives are configured on a master-only bus they
296507c3241Smlf 	 * "shadow" their registers for the not-present slave drive.
297507c3241Smlf 	 * This is bogus and if you're not careful it may cause a
298507c3241Smlf 	 * master-only drive to be mistakenly recognized as both
299507c3241Smlf 	 * master and slave. By clearing the signature registers here
300507c3241Smlf 	 * I can make certain that when ata_drive_type() switches from
301507c3241Smlf 	 * the master to slave drive that I'll read back non-signature
302507c3241Smlf 	 * values regardless of whether the master-only drive does
303507c3241Smlf 	 * the "shadow" register trick. This prevents a bogus
304507c3241Smlf 	 * IDENTIFY PACKET DEVICE command from being issued which
305507c3241Smlf 	 * a really bogus master-only drive will return "shadow"
306507c3241Smlf 	 * data for.
307507c3241Smlf 	 */
308507c3241Smlf 	ddi_put8(io_hdl, (uchar_t *)ioaddr + AT_HCYL, 0);
309507c3241Smlf 	ddi_put8(io_hdl, (uchar_t *)ioaddr + AT_LCYL, 0);
310507c3241Smlf 
311507c3241Smlf 	return (rc);
312507c3241Smlf }
313507c3241Smlf 
314507c3241Smlf 
315507c3241Smlf /*
316507c3241Smlf  *
317507c3241Smlf  * SCSA tran_tgt_init entry point
318507c3241Smlf  *
319507c3241Smlf  */
320507c3241Smlf 
321507c3241Smlf /* ARGSUSED */
322507c3241Smlf static int
atapi_tran_tgt_init(dev_info_t * hba_dip,dev_info_t * tgt_dip,scsi_hba_tran_t * hba_tran,struct scsi_device * sd)323507c3241Smlf atapi_tran_tgt_init(
324507c3241Smlf 	dev_info_t	*hba_dip,
325507c3241Smlf 	dev_info_t	*tgt_dip,
326507c3241Smlf 	scsi_hba_tran_t *hba_tran,
327507c3241Smlf 	struct scsi_device *sd)
328507c3241Smlf {
329507c3241Smlf 	gtgt_t	  *gtgtp;	/* GHD's per-target-instance structure */
330507c3241Smlf 	ata_ctl_t *ata_ctlp;
331507c3241Smlf 	ata_tgt_t *ata_tgtp;
332507c3241Smlf 	ata_drv_t *ata_drvp;
333507c3241Smlf 	struct scsi_address *ap;
334507c3241Smlf 	int	rc = DDI_SUCCESS;
335507c3241Smlf 
336507c3241Smlf 	ADBG_TRACE(("atapi_tran_tgt_init entered\n"));
337507c3241Smlf 
338507c3241Smlf 	/*
339507c3241Smlf 	 * Qualification of targ, lun, and ATAPI device presence
340507c3241Smlf 	 *  have already been taken care of by ata_bus_ctl
341507c3241Smlf 	 */
342507c3241Smlf 
343507c3241Smlf 	/* store pointer to drive struct in cloned tran struct */
344507c3241Smlf 
345507c3241Smlf 	ata_ctlp = TRAN2CTL(hba_tran);
346507c3241Smlf 	ap = &sd->sd_address;
347507c3241Smlf 
348507c3241Smlf 	ata_drvp = CTL2DRV(ata_ctlp, ap->a_target, ap->a_lun);
349507c3241Smlf 
350507c3241Smlf 	/*
351507c3241Smlf 	 * Create the "atapi" property so the target driver knows
352507c3241Smlf 	 * to use the correct set of SCSI commands
353507c3241Smlf 	 */
354507c3241Smlf 	if (!ata_prop_create(tgt_dip, ata_drvp, "atapi")) {
355507c3241Smlf 		return (DDI_FAILURE);
356507c3241Smlf 	}
357507c3241Smlf 
358507c3241Smlf 	gtgtp = ghd_target_init(hba_dip, tgt_dip, &ata_ctlp->ac_ccc,
359507c3241Smlf 	    sizeof (ata_tgt_t), ata_ctlp,
360507c3241Smlf 	    ap->a_target, ap->a_lun);
361507c3241Smlf 
362507c3241Smlf 	/* tran_tgt_private points to gtgt_t */
363507c3241Smlf 	hba_tran->tran_tgt_private = gtgtp;
364507c3241Smlf 
365507c3241Smlf 	/* gt_tgt_private points to ata_tgt_t */
366507c3241Smlf 	ata_tgtp = GTGTP2ATATGTP(gtgtp);
367507c3241Smlf 
368507c3241Smlf 	/* initialize the per-target-instance data */
369507c3241Smlf 	ata_tgtp->at_drvp = ata_drvp;
370507c3241Smlf 	ata_tgtp->at_dma_attr = ata_pciide_dma_attr;
371507c3241Smlf 	ata_tgtp->at_dma_attr.dma_attr_maxxfer =
372507c3241Smlf 	    ata_ctlp->ac_max_transfer << SCTRSHFT;
373507c3241Smlf 
374507c3241Smlf 	return (rc);
375507c3241Smlf }
376507c3241Smlf 
377507c3241Smlf 
378507c3241Smlf /*
379507c3241Smlf  *
380507c3241Smlf  * SCSA tran_tgt_probe entry point
381507c3241Smlf  *
382507c3241Smlf  */
383507c3241Smlf 
384507c3241Smlf static int
atapi_tran_tgt_probe(struct scsi_device * sd,int (* callback)(void))385507c3241Smlf atapi_tran_tgt_probe(struct scsi_device *sd, int (*callback)(void))
386507c3241Smlf {
387507c3241Smlf 	ADBG_TRACE(("atapi_tran_tgt_probe entered\n"));
388507c3241Smlf 
389507c3241Smlf 	return (scsi_hba_probe(sd, callback));
390507c3241Smlf }
391507c3241Smlf 
392507c3241Smlf 
393507c3241Smlf /*
394507c3241Smlf  *
395507c3241Smlf  * SCSA tran_tgt_free entry point
396507c3241Smlf  *
397507c3241Smlf  */
398507c3241Smlf 
399507c3241Smlf /* ARGSUSED */
400507c3241Smlf static void
atapi_tran_tgt_free(dev_info_t * hba_dip,dev_info_t * tgt_dip,scsi_hba_tran_t * hba_tran,struct scsi_device * sd)401507c3241Smlf atapi_tran_tgt_free(
402507c3241Smlf 	dev_info_t	*hba_dip,
403507c3241Smlf 	dev_info_t	*tgt_dip,
404507c3241Smlf 	scsi_hba_tran_t	*hba_tran,
405507c3241Smlf 	struct scsi_device *sd)
406507c3241Smlf {
407507c3241Smlf 	ADBG_TRACE(("atapi_tran_tgt_free entered\n"));
408507c3241Smlf 
409507c3241Smlf 	ghd_target_free(hba_dip, tgt_dip, &TRAN2ATAP(hba_tran)->ac_ccc,
4106fd12ef3Slh 	    TRAN2GTGTP(hba_tran));
411507c3241Smlf 	hba_tran->tran_tgt_private = NULL;
412507c3241Smlf }
413507c3241Smlf 
414507c3241Smlf 
415507c3241Smlf 
416507c3241Smlf /*
417507c3241Smlf  *
418507c3241Smlf  * SCSA tran_abort entry point
419507c3241Smlf  *
420507c3241Smlf  */
421507c3241Smlf 
422507c3241Smlf /* ARGSUSED */
423507c3241Smlf static int
atapi_tran_abort(struct scsi_address * ap,struct scsi_pkt * spktp)424507c3241Smlf atapi_tran_abort(
425507c3241Smlf 	struct scsi_address *ap,
426507c3241Smlf 	struct scsi_pkt *spktp)
427507c3241Smlf {
428507c3241Smlf 	ADBG_TRACE(("atapi_tran_abort entered\n"));
429507c3241Smlf 
430507c3241Smlf 	if (spktp) {
431507c3241Smlf 		return (ghd_tran_abort(&ADDR2CTL(ap)->ac_ccc, PKTP2GCMDP(spktp),
4326fd12ef3Slh 		    ADDR2GTGTP(ap), NULL));
433507c3241Smlf 	}
434507c3241Smlf 
435507c3241Smlf 	return (ghd_tran_abort_lun(&ADDR2CTL(ap)->ac_ccc, ADDR2GTGTP(ap),
4366fd12ef3Slh 	    NULL));
437507c3241Smlf }
438507c3241Smlf 
439507c3241Smlf 
440507c3241Smlf /*
441507c3241Smlf  *
442507c3241Smlf  * SCSA tran_reset entry point
443507c3241Smlf  *
444507c3241Smlf  */
445507c3241Smlf 
446507c3241Smlf /* ARGSUSED */
447507c3241Smlf static int
atapi_tran_reset(struct scsi_address * ap,int level)448507c3241Smlf atapi_tran_reset(
449507c3241Smlf 	struct scsi_address *ap,
450507c3241Smlf 	int level)
451507c3241Smlf {
452507c3241Smlf 	ADBG_TRACE(("atapi_tran_reset entered\n"));
453507c3241Smlf 
454507c3241Smlf 	if (level == RESET_TARGET)
455507c3241Smlf 		return (ghd_tran_reset_target(&ADDR2CTL(ap)->ac_ccc,
456507c3241Smlf 		    ADDR2GTGTP(ap), NULL));
457507c3241Smlf 	if (level == RESET_ALL)
458507c3241Smlf 		return (ghd_tran_reset_bus(&ADDR2CTL(ap)->ac_ccc,
459507c3241Smlf 		    ADDR2GTGTP(ap), NULL));
460507c3241Smlf 	return (FALSE);
461507c3241Smlf 
462507c3241Smlf }
463507c3241Smlf 
464507c3241Smlf 
465507c3241Smlf /*
466507c3241Smlf  *
467507c3241Smlf  * SCSA tran_setcap entry point
468507c3241Smlf  *
469507c3241Smlf  */
470507c3241Smlf 
471507c3241Smlf static int
atapi_tran_setcap(struct scsi_address * ap,char * capstr,int value,int whom)472507c3241Smlf atapi_tran_setcap(
473507c3241Smlf 	struct scsi_address *ap,
474507c3241Smlf 	char *capstr,
475507c3241Smlf 	int value,
476507c3241Smlf 	int whom)
477507c3241Smlf {
478507c3241Smlf 	gtgt_t	  *gtgtp = ADDR2GTGTP(ap);
479507c3241Smlf 	ata_tgt_t *tgtp = GTGTP2ATATGTP(gtgtp);
480507c3241Smlf 
481507c3241Smlf 	ADBG_TRACE(("atapi_tran_setcap entered\n"));
482507c3241Smlf 
483507c3241Smlf 	switch (scsi_hba_lookup_capstr(capstr)) {
484507c3241Smlf 		case SCSI_CAP_SECTOR_SIZE:
485507c3241Smlf 			tgtp->at_dma_attr.dma_attr_granular = (uint_t)value;
486507c3241Smlf 			return (TRUE);
487507c3241Smlf 
488507c3241Smlf 		case SCSI_CAP_ARQ:
489507c3241Smlf 			if (whom) {
490507c3241Smlf 				tgtp->at_arq = value;
491507c3241Smlf 				return (TRUE);
492507c3241Smlf 			}
493507c3241Smlf 			break;
494507c3241Smlf 
495507c3241Smlf 		case SCSI_CAP_TOTAL_SECTORS:
496507c3241Smlf 			tgtp->at_total_sectors = value;
497507c3241Smlf 			return (TRUE);
498507c3241Smlf 	}
499507c3241Smlf 	return (FALSE);
500507c3241Smlf }
501507c3241Smlf 
502507c3241Smlf 
503507c3241Smlf /*
504507c3241Smlf  *
505507c3241Smlf  * SCSA tran_getcap entry point
506507c3241Smlf  *
507507c3241Smlf  */
508507c3241Smlf 
509507c3241Smlf static int
atapi_tran_getcap(struct scsi_address * ap,char * capstr,int whom)510507c3241Smlf atapi_tran_getcap(
511507c3241Smlf 	struct scsi_address *ap,
512507c3241Smlf 	char *capstr,
513507c3241Smlf 	int whom)
514507c3241Smlf {
515507c3241Smlf 	struct ata_id	 ata_id;
516507c3241Smlf 	struct ata_id	*ata_idp;
517507c3241Smlf 	ata_ctl_t	*ata_ctlp;
518507c3241Smlf 	ata_drv_t	*ata_drvp;
519507c3241Smlf 	gtgt_t		*gtgtp;
520507c3241Smlf 	int		 rval = -1;
521507c3241Smlf 
522507c3241Smlf 	ADBG_TRACE(("atapi_tran_getcap entered\n"));
523507c3241Smlf 
524507c3241Smlf 	if (capstr == NULL || whom == 0)
525507c3241Smlf 		return (-1);
526507c3241Smlf 
527507c3241Smlf 	ata_ctlp = ADDR2CTL(ap);
528507c3241Smlf 
529507c3241Smlf 	switch (scsi_hba_lookup_capstr(capstr)) {
530507c3241Smlf 	case SCSI_CAP_ARQ:
531507c3241Smlf 		rval = TRUE;
532507c3241Smlf 		break;
533507c3241Smlf 
534507c3241Smlf 	case SCSI_CAP_INITIATOR_ID:
535507c3241Smlf 		rval = 7;
536507c3241Smlf 		break;
537507c3241Smlf 
538507c3241Smlf 	case SCSI_CAP_DMA_MAX:
539507c3241Smlf 		/* XXX - what should the real limit be?? */
540507c3241Smlf 		/* limit to 64K ??? */
541507c3241Smlf 		rval = 4096 * (ATA_DMA_NSEGS - 1);
542507c3241Smlf 		break;
543507c3241Smlf 
544507c3241Smlf 	case SCSI_CAP_GEOMETRY:
545507c3241Smlf 		/* Default geometry */
546507c3241Smlf 		if (atapi_use_static_geometry) {
547507c3241Smlf 			rval = ATAPI_HEADS << 16 | ATAPI_SECTORS_PER_TRK;
548507c3241Smlf 			break;
549507c3241Smlf 		}
550507c3241Smlf 
551507c3241Smlf 		/* this code is currently not used */
552507c3241Smlf 
553507c3241Smlf 		ata_drvp = CTL2DRV(ata_ctlp, ap->a_target, ap->a_lun);
554507c3241Smlf 		gtgtp = ADDR2GTGTP(ap);
555507c3241Smlf 
556507c3241Smlf 		/*
557507c3241Smlf 		 * retrieve the current IDENTIFY PACKET DEVICE info
558507c3241Smlf 		 */
559507c3241Smlf 		if (!ata_queue_cmd(atapi_id_update, &ata_id, ata_ctlp,
5606fd12ef3Slh 		    ata_drvp, gtgtp)) {
561507c3241Smlf 			ADBG_TRACE(("atapi_tran_getcap geometry failed"));
562507c3241Smlf 			return (0);
563507c3241Smlf 		}
564507c3241Smlf 
565507c3241Smlf 		/*
566507c3241Smlf 		 * save the new response data
567507c3241Smlf 		 */
568507c3241Smlf 		ata_idp = &ata_drvp->ad_id;
569507c3241Smlf 		*ata_idp = ata_id;
570507c3241Smlf 
571507c3241Smlf 		switch ((ata_idp->ai_config >> 8) & 0xf) {
572507c3241Smlf 		case DTYPE_RODIRECT:
573507c3241Smlf 			rval = ATAPI_HEADS << 16 | ATAPI_SECTORS_PER_TRK;
574507c3241Smlf 			break;
575507c3241Smlf 		case DTYPE_DIRECT:
576507c3241Smlf 		case DTYPE_OPTICAL:
577507c3241Smlf 			rval = (ata_idp->ai_curheads << 16) |
5786fd12ef3Slh 			    ata_idp->ai_cursectrk;
579507c3241Smlf 			break;
580507c3241Smlf 		default:
581507c3241Smlf 			rval = 0;
582507c3241Smlf 		}
583507c3241Smlf 		break;
584507c3241Smlf 	}
585507c3241Smlf 
586507c3241Smlf 	return (rval);
587507c3241Smlf }
588507c3241Smlf 
589507c3241Smlf 
590507c3241Smlf 
591507c3241Smlf /*
592507c3241Smlf  *
593507c3241Smlf  * SCSA tran_init_pkt entry point
594507c3241Smlf  *
595507c3241Smlf  */
596507c3241Smlf 
597507c3241Smlf static struct scsi_pkt *
atapi_tran_init_pkt(struct scsi_address * ap,struct scsi_pkt * spktp,struct buf * bp,int cmdlen,int statuslen,int tgtlen,int flags,int (* callback)(caddr_t),caddr_t arg)598507c3241Smlf atapi_tran_init_pkt(
599507c3241Smlf 	struct scsi_address *ap,
600507c3241Smlf 	struct scsi_pkt	*spktp,
601507c3241Smlf 	struct buf	*bp,
602507c3241Smlf 	int		 cmdlen,
603507c3241Smlf 	int		 statuslen,
604507c3241Smlf 	int		 tgtlen,
605507c3241Smlf 	int		 flags,
606507c3241Smlf 	int		(*callback)(caddr_t),
607507c3241Smlf 	caddr_t		 arg)
608507c3241Smlf {
609507c3241Smlf 	gtgt_t		*gtgtp = ADDR2GTGTP(ap);
610507c3241Smlf 	ata_tgt_t	*ata_tgtp = GTGTP2ATATGTP(gtgtp);
611507c3241Smlf 	ata_ctl_t	*ata_ctlp = ADDR2CTL(ap);
612507c3241Smlf 	ata_pkt_t	*ata_pktp;
613507c3241Smlf 	struct scsi_pkt	*new_spktp;
614507c3241Smlf 	ddi_dma_attr_t	*sg_attrp;
615507c3241Smlf 	int		 bytes;
616507c3241Smlf 
617507c3241Smlf 	ADBG_TRACE(("atapi_tran_init_pkt entered\n"));
618507c3241Smlf 
619507c3241Smlf 
620507c3241Smlf 	/*
621507c3241Smlf 	 * Determine whether to do PCI-IDE DMA setup, start out by
622507c3241Smlf 	 * assuming we're not.
623507c3241Smlf 	 */
624507c3241Smlf 	sg_attrp = NULL;
625507c3241Smlf 
626507c3241Smlf 	if (bp == NULL) {
627507c3241Smlf 		/* no data to transfer */
628507c3241Smlf 		goto skip_dma_setup;
629507c3241Smlf 	}
630507c3241Smlf 
631507c3241Smlf 	if (bp->b_bcount == 0) {
632507c3241Smlf 		/* no data to transfer */
633507c3241Smlf 		goto skip_dma_setup;
634507c3241Smlf 	}
635507c3241Smlf 
636507c3241Smlf 	if ((GTGTP2ATADRVP(ADDR2GTGTP(ap))->ad_pciide_dma == ATA_DMA_OFF)) {
637507c3241Smlf 		goto skip_dma_setup;
638507c3241Smlf 	}
639507c3241Smlf 
640507c3241Smlf 	if (ata_dma_disabled)
641507c3241Smlf 		goto skip_dma_setup;
642507c3241Smlf 
643507c3241Smlf 
644507c3241Smlf 	/*
645507c3241Smlf 	 * The PCI-IDE DMA engine is brain-damaged and can't
646507c3241Smlf 	 * DMA non-aligned buffers.
647507c3241Smlf 	 */
648507c3241Smlf 	if (((bp->b_flags & B_PAGEIO) == 0) &&
649507c3241Smlf 	    ((uintptr_t)bp->b_un.b_addr) & PCIIDE_PRDE_ADDR_MASK) {
650507c3241Smlf 		/*
651507c3241Smlf 		 * if the virtual address isn't aligned, then the
652507c3241Smlf 		 * physical address also isn't aligned.
653507c3241Smlf 		 */
654507c3241Smlf 		goto skip_dma_setup;
655507c3241Smlf 	}
656507c3241Smlf 
657507c3241Smlf 	/*
658507c3241Smlf 	 * It also insists that the byte count must be even.
659507c3241Smlf 	 */
660507c3241Smlf 	if (bp->b_bcount & 1) {
661507c3241Smlf 		/* something odd here */
662507c3241Smlf 		goto skip_dma_setup;
663507c3241Smlf 	}
664507c3241Smlf 
665507c3241Smlf 	/*
666507c3241Smlf 	 * Huzza! We're really going to do it
667507c3241Smlf 	 */
668507c3241Smlf 	sg_attrp = &ata_tgtp->at_dma_attr;
669507c3241Smlf 
670507c3241Smlf 
671507c3241Smlf skip_dma_setup:
672507c3241Smlf 
673507c3241Smlf 	/*
674507c3241Smlf 	 * Call GHD packet init function
675507c3241Smlf 	 */
676507c3241Smlf 
677507c3241Smlf 	new_spktp = ghd_tran_init_pkt_attr(&ata_ctlp->ac_ccc, ap, spktp, bp,
6786fd12ef3Slh 	    cmdlen, statuslen, tgtlen, flags,
6796fd12ef3Slh 	    callback, arg, sizeof (ata_pkt_t), sg_attrp);
680507c3241Smlf 
681507c3241Smlf 	if (new_spktp == NULL)
682507c3241Smlf 		return (NULL);
683507c3241Smlf 
684507c3241Smlf 	ata_pktp = SPKT2APKT(new_spktp);
685507c3241Smlf 	ata_pktp->ap_cdbp = new_spktp->pkt_cdbp;
6866fd12ef3Slh 	if (statuslen > 255) {
6876fd12ef3Slh 		statuslen = sizeof (struct scsi_arq_status);
6886fd12ef3Slh 	}
689507c3241Smlf 	ata_pktp->ap_statuslen = (uchar_t)statuslen;
690507c3241Smlf 
691507c3241Smlf 	/* reset data direction flags */
692507c3241Smlf 	if (spktp)
693507c3241Smlf 		ata_pktp->ap_flags &= ~(AP_READ | AP_WRITE);
694507c3241Smlf 
695507c3241Smlf 	/*
696507c3241Smlf 	 * check for ARQ mode
697507c3241Smlf 	 */
698507c3241Smlf 	if (atapi_arq_enable == TRUE &&
6996fd12ef3Slh 	    ata_tgtp->at_arq == TRUE &&
7006fd12ef3Slh 	    ata_pktp->ap_statuslen >= sizeof (struct scsi_arq_status)) {
701507c3241Smlf 		ADBG_TRACE(("atapi_tran_init_pkt ARQ\n"));
702507c3241Smlf 		ata_pktp->ap_scbp =
703507c3241Smlf 		    (struct scsi_arq_status *)new_spktp->pkt_scbp;
704507c3241Smlf 		ata_pktp->ap_flags |= AP_ARQ_ON_ERROR;
705507c3241Smlf 	}
706507c3241Smlf 
707507c3241Smlf 	/*
708507c3241Smlf 	 * fill these with zeros for ATA/ATAPI-4 compatibility
709507c3241Smlf 	 */
710507c3241Smlf 	ata_pktp->ap_sec = 0;
711507c3241Smlf 	ata_pktp->ap_count = 0;
712507c3241Smlf 
713507c3241Smlf 	if (ata_pktp->ap_sg_cnt) {
714507c3241Smlf 		ASSERT(bp != NULL);
715507c3241Smlf 		/* determine direction to program the DMA engine later */
716507c3241Smlf 		if (bp->b_flags & B_READ) {
717507c3241Smlf 			ata_pktp->ap_flags |= AP_READ;
718507c3241Smlf 		} else {
719507c3241Smlf 			ata_pktp->ap_flags |= AP_WRITE;
720507c3241Smlf 		}
721507c3241Smlf 		ata_pktp->ap_pciide_dma = TRUE;
722507c3241Smlf 		ata_pktp->ap_hicyl = 0;
723507c3241Smlf 		ata_pktp->ap_lwcyl = 0;
724507c3241Smlf 		return (new_spktp);
725507c3241Smlf 	}
726507c3241Smlf 
727507c3241Smlf 	/*
728507c3241Smlf 	 * Since we're not using DMA, we need to map the buffer into
729507c3241Smlf 	 * kernel address space
730507c3241Smlf 	 */
731507c3241Smlf 
732507c3241Smlf 	ata_pktp->ap_pciide_dma = FALSE;
733507c3241Smlf 	if (bp && bp->b_bcount) {
734507c3241Smlf 		/*
735507c3241Smlf 		 * If this is a fresh request map the buffer and
736507c3241Smlf 		 * reset the ap_baddr pointer and the current offset
737507c3241Smlf 		 * and byte count.
738507c3241Smlf 		 *
739507c3241Smlf 		 * The ap_boffset is used to set the ap_v_addr ptr at
740507c3241Smlf 		 * the start of each I/O request.
741507c3241Smlf 		 *
742507c3241Smlf 		 * The ap_bcount is used to update ap_boffset when the
743507c3241Smlf 		 * target driver requests the next segment.
744507c3241Smlf 		 *
745507c3241Smlf 		 */
746507c3241Smlf 		if (cmdlen) {
747507c3241Smlf 			bp_mapin(bp);
748507c3241Smlf 			ata_pktp->ap_baddr = bp->b_un.b_addr;
749507c3241Smlf 			ata_pktp->ap_bcount = 0;
750507c3241Smlf 			ata_pktp->ap_boffset = 0;
751507c3241Smlf 		}
752507c3241Smlf 		ASSERT(ata_pktp->ap_baddr != NULL);
753507c3241Smlf 
754507c3241Smlf 		/* determine direction for the PIO FSM */
755507c3241Smlf 		if (bp->b_flags & B_READ) {
756507c3241Smlf 			ata_pktp->ap_flags |= AP_READ;
757507c3241Smlf 		} else {
758507c3241Smlf 			ata_pktp->ap_flags |= AP_WRITE;
759507c3241Smlf 		}
760507c3241Smlf 
761507c3241Smlf 		/*
762507c3241Smlf 		 * If the drive has the Single Sector bug, limit
763507c3241Smlf 		 * the transfer to a single sector. This assumes
764507c3241Smlf 		 * ATAPI CD drives always use 2k sectors.
765507c3241Smlf 		 */
766507c3241Smlf 		if (GTGTP2ATADRVP(ADDR2GTGTP(ap))->ad_flags & AD_1SECTOR) {
767507c3241Smlf 			size_t resid;
768507c3241Smlf 			size_t tmp;
769507c3241Smlf 
770507c3241Smlf 			/* adjust offset based on prior request */
771507c3241Smlf 			ata_pktp->ap_boffset += ata_pktp->ap_bcount;
772507c3241Smlf 
773507c3241Smlf 			/* compute number of bytes left to transfer */
774507c3241Smlf 			resid = bp->b_bcount - ata_pktp->ap_boffset;
775507c3241Smlf 
776507c3241Smlf 			/* limit the transfer to 2k */
777507c3241Smlf 			tmp = MIN(2048, resid);
778507c3241Smlf 			ata_pktp->ap_bcount = tmp;
779507c3241Smlf 
780507c3241Smlf 			/* tell target driver how much is left for next time */
781507c3241Smlf 			new_spktp->pkt_resid = resid - tmp;
782507c3241Smlf 		} else {
783507c3241Smlf 			/* do the whole request in one swell foop */
784507c3241Smlf 			ata_pktp->ap_bcount = bp->b_bcount;
785507c3241Smlf 			new_spktp->pkt_resid = 0;
786507c3241Smlf 		}
787507c3241Smlf 
788507c3241Smlf 	} else {
789507c3241Smlf 		ata_pktp->ap_baddr = NULL;
790507c3241Smlf 		ata_pktp->ap_bcount = 0;
791507c3241Smlf 		ata_pktp->ap_boffset = 0;
792507c3241Smlf 	}
793507c3241Smlf 
794507c3241Smlf 	/*
795507c3241Smlf 	 * determine the size of each partial data transfer
796507c3241Smlf 	 * to/from the drive
797507c3241Smlf 	 */
798507c3241Smlf 	bytes = min(ata_pktp->ap_bcount, ATAPI_MAX_BYTES_PER_DRQ);
799507c3241Smlf 	ata_pktp->ap_hicyl = (uchar_t)(bytes >> 8);
800507c3241Smlf 	ata_pktp->ap_lwcyl = (uchar_t)bytes;
801507c3241Smlf 	return (new_spktp);
802507c3241Smlf }
803507c3241Smlf 
804507c3241Smlf 
805507c3241Smlf /*
806507c3241Smlf  * GHD ccballoc callback
807507c3241Smlf  *
808507c3241Smlf  *	Initializing the ata_pkt, and return the ptr to the gcmd_t to GHD.
809507c3241Smlf  *
810507c3241Smlf  */
811507c3241Smlf 
812507c3241Smlf /* ARGSUSED */
813507c3241Smlf int
atapi_ccballoc(gtgt_t * gtgtp,gcmd_t * gcmdp,int cmdlen,int statuslen,int tgtlen,int ccblen)814507c3241Smlf atapi_ccballoc(
815507c3241Smlf 	gtgt_t	*gtgtp,
816507c3241Smlf 	gcmd_t	*gcmdp,
817507c3241Smlf 	int	 cmdlen,
818507c3241Smlf 	int	 statuslen,
819507c3241Smlf 	int	 tgtlen,
820507c3241Smlf 	int	 ccblen)
821507c3241Smlf 
822507c3241Smlf {
823507c3241Smlf 	ata_drv_t *ata_drvp = GTGTP2ATADRVP(gtgtp);
824507c3241Smlf 	ata_pkt_t *ata_pktp = GCMD2APKT(gcmdp);
825507c3241Smlf 
826507c3241Smlf 	ADBG_TRACE(("atapi_ccballoc entered\n"));
827507c3241Smlf 
828507c3241Smlf 	/* set the back ptr from the ata_pkt to the gcmd_t */
829507c3241Smlf 	ata_pktp->ap_gcmdp = gcmdp;
830507c3241Smlf 
831507c3241Smlf 	/* check length of SCSI CDB is not larger than drive expects */
832507c3241Smlf 
833507c3241Smlf 	if (cmdlen > ata_drvp->ad_cdb_len) {
834507c3241Smlf 		ADBG_WARN(("atapi_ccballoc: SCSI CDB too large!\n"));
835507c3241Smlf 		return (FALSE);
836507c3241Smlf 	}
837507c3241Smlf 
838507c3241Smlf 	/*
839507c3241Smlf 	 * save length of the SCSI CDB, and calculate CDB padding
840507c3241Smlf 	 * note that for convenience, padding is expressed in shorts.
841507c3241Smlf 	 */
842507c3241Smlf 
843507c3241Smlf 	ata_pktp->ap_cdb_len = (uchar_t)cmdlen;
844507c3241Smlf 	ata_pktp->ap_cdb_pad =
845507c3241Smlf 		((unsigned)(ata_drvp->ad_cdb_len - cmdlen)) >> 1;
846507c3241Smlf 
847507c3241Smlf 	/* set up callback functions */
848507c3241Smlf 
849507c3241Smlf 	ata_pktp->ap_start = atapi_fsm_start;
850507c3241Smlf 	ata_pktp->ap_intr = atapi_fsm_intr;
851507c3241Smlf 	ata_pktp->ap_complete = atapi_complete;
852507c3241Smlf 
853507c3241Smlf 	/* set-up for start */
854507c3241Smlf 
855507c3241Smlf 	ata_pktp->ap_flags = AP_ATAPI;
856507c3241Smlf 	ata_pktp->ap_hd = ata_drvp->ad_drive_bits;
857507c3241Smlf 	ata_pktp->ap_cmd = ATC_PACKET;
858507c3241Smlf 
859507c3241Smlf 	return (TRUE);
860507c3241Smlf }
861507c3241Smlf 
862507c3241Smlf 
863507c3241Smlf 
864507c3241Smlf /*
865507c3241Smlf  *
866507c3241Smlf  * SCSA tran_destroy_pkt entry point
867507c3241Smlf  *
868507c3241Smlf  */
869507c3241Smlf 
870507c3241Smlf static void
atapi_tran_destroy_pkt(struct scsi_address * ap,struct scsi_pkt * spktp)871507c3241Smlf atapi_tran_destroy_pkt(
872507c3241Smlf 	struct scsi_address *ap,
873507c3241Smlf 	struct scsi_pkt *spktp)
874507c3241Smlf {
875507c3241Smlf 	gcmd_t	  *gcmdp = PKTP2GCMDP(spktp);
876507c3241Smlf 
877507c3241Smlf 	ADBG_TRACE(("atapi_tran_destroy_pkt entered\n"));
878507c3241Smlf 
879507c3241Smlf 	if (gcmdp->cmd_dma_handle != NULL) {
880507c3241Smlf 		ghd_dmafree_attr(gcmdp);
881507c3241Smlf 	}
882507c3241Smlf 
883507c3241Smlf 	ghd_pktfree(&ADDR2CTL(ap)->ac_ccc, ap, spktp);
884507c3241Smlf }
885507c3241Smlf 
886507c3241Smlf 
887507c3241Smlf 
888507c3241Smlf /*
889507c3241Smlf  *
890507c3241Smlf  * GHD ccbfree callback function
891507c3241Smlf  *
892507c3241Smlf  */
893507c3241Smlf 
894507c3241Smlf /* ARGSUSED */
895507c3241Smlf void
atapi_ccbfree(gcmd_t * gcmdp)896507c3241Smlf atapi_ccbfree(
897507c3241Smlf 	gcmd_t *gcmdp)
898507c3241Smlf {
899507c3241Smlf 	ADBG_TRACE(("atapi_ccbfree entered\n"));
900507c3241Smlf 
901507c3241Smlf 	/* nothing to do */
902507c3241Smlf }
903507c3241Smlf 
904507c3241Smlf 
905507c3241Smlf /*
906507c3241Smlf  *
907507c3241Smlf  * SCSA tran_dmafree entry point
908507c3241Smlf  *
909507c3241Smlf  */
910507c3241Smlf 
911507c3241Smlf /*ARGSUSED*/
912507c3241Smlf static void
atapi_tran_dmafree(struct scsi_address * ap,struct scsi_pkt * spktp)913507c3241Smlf atapi_tran_dmafree(
914507c3241Smlf 	struct scsi_address *ap,
915507c3241Smlf 	struct scsi_pkt *spktp)
916507c3241Smlf {
917507c3241Smlf 	gcmd_t	  *gcmdp = PKTP2GCMDP(spktp);
918507c3241Smlf 
919507c3241Smlf 	ADBG_TRACE(("atapi_tran_dmafree entered\n"));
920507c3241Smlf 
921507c3241Smlf 	if (gcmdp->cmd_dma_handle != NULL) {
922507c3241Smlf 		ghd_dmafree_attr(gcmdp);
923507c3241Smlf 	}
924507c3241Smlf }
925507c3241Smlf 
926507c3241Smlf 
927507c3241Smlf 
928507c3241Smlf /*
929507c3241Smlf  *
930507c3241Smlf  * SCSA tran_sync_pkt entry point
931507c3241Smlf  *
932507c3241Smlf  */
933507c3241Smlf 
934507c3241Smlf /*ARGSUSED*/
935507c3241Smlf static void
atapi_tran_sync_pkt(struct scsi_address * ap,struct scsi_pkt * spktp)936507c3241Smlf atapi_tran_sync_pkt(
937507c3241Smlf 	struct scsi_address *ap,
938507c3241Smlf 	struct scsi_pkt *spktp)
939507c3241Smlf {
940507c3241Smlf 
941507c3241Smlf 	ADBG_TRACE(("atapi_tran_sync_pkt entered\n"));
942507c3241Smlf 
943507c3241Smlf 	if (PKTP2GCMDP(spktp)->cmd_dma_handle != NULL) {
944507c3241Smlf 		ghd_tran_sync_pkt(ap, spktp);
945507c3241Smlf 	}
946507c3241Smlf }
947507c3241Smlf 
948507c3241Smlf 
949507c3241Smlf 
950507c3241Smlf /*
951507c3241Smlf  *
952507c3241Smlf  * SCSA tran_start entry point
953507c3241Smlf  *
954507c3241Smlf  */
955507c3241Smlf 
956507c3241Smlf /* ARGSUSED */
957507c3241Smlf static int
atapi_tran_start(struct scsi_address * ap,struct scsi_pkt * spktp)958507c3241Smlf atapi_tran_start(
959507c3241Smlf 	struct scsi_address *ap,
960507c3241Smlf 	struct scsi_pkt *spktp)
961507c3241Smlf {
962507c3241Smlf 	ata_pkt_t *ata_pktp = SPKT2APKT(spktp);
963507c3241Smlf 	ata_drv_t *ata_drvp = APKT2DRV(ata_pktp);
964507c3241Smlf 	ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
965507c3241Smlf 	gcmd_t	  *gcmdp = APKT2GCMD(ata_pktp);
966507c3241Smlf 	int	   polled = FALSE;
967507c3241Smlf 	int	   rc;
968507c3241Smlf 
969507c3241Smlf 	ADBG_TRACE(("atapi_tran_start entered\n"));
970507c3241Smlf 
971507c3241Smlf 	/*
972507c3241Smlf 	 * Basic initialization performed each and every time a
973507c3241Smlf 	 * scsi_pkt is submitted. A single scsi_pkt may be submitted
974507c3241Smlf 	 * multiple times so this routine has to be idempotent. One
975507c3241Smlf 	 * time initializations don't belong here.
976507c3241Smlf 	 */
977507c3241Smlf 
978507c3241Smlf 	/*
979507c3241Smlf 	 * The ap_v_addr pointer is incremented by the PIO data
980507c3241Smlf 	 * transfer routine as each word is transferred. Therefore, need
981507c3241Smlf 	 * to reset ap_v_addr here (rather than atapi_tran_init_pkt())
982507c3241Smlf 	 * in case the target resubmits the same pkt multiple times
983507c3241Smlf 	 * (which is permitted by SCSA).
984507c3241Smlf 	 */
985507c3241Smlf 	ata_pktp->ap_v_addr = ata_pktp->ap_baddr + ata_pktp->ap_boffset;
986507c3241Smlf 
987507c3241Smlf 	/* ap_resid is decremented as the data transfer progresses */
988507c3241Smlf 	ata_pktp->ap_resid = ata_pktp->ap_bcount;
989507c3241Smlf 
990507c3241Smlf 	/* clear error flags */
991507c3241Smlf 	ata_pktp->ap_flags &= (AP_ATAPI | AP_READ | AP_WRITE | AP_ARQ_ON_ERROR);
992507c3241Smlf 	spktp->pkt_reason = 0;
993507c3241Smlf 	spktp->pkt_state = 0;
994507c3241Smlf 	spktp->pkt_statistics = 0;
995507c3241Smlf 
996507c3241Smlf 	/*
997507c3241Smlf 	 * check for polling pkt
998507c3241Smlf 	 */
999507c3241Smlf 	if (spktp->pkt_flags & FLAG_NOINTR) {
1000507c3241Smlf 		polled = TRUE;
1001507c3241Smlf 	}
1002507c3241Smlf 
1003507c3241Smlf #ifdef ___just_ignore_unsupported_flags___
1004507c3241Smlf 	/* driver cannot accept tagged commands */
1005507c3241Smlf 
1006507c3241Smlf 	if (spktp->pkt_flags & (FLAG_HTAG|FLAG_OTAG|FLAG_STAG)) {
1007507c3241Smlf 		spktp->pkt_reason = CMD_TRAN_ERR;
1008507c3241Smlf 		return (TRAN_BADPKT);
1009507c3241Smlf 	}
1010507c3241Smlf #endif
1011507c3241Smlf 
1012507c3241Smlf 	/* call common transport routine */
1013507c3241Smlf 
1014507c3241Smlf 	rc = ghd_transport(&ata_ctlp->ac_ccc, gcmdp, gcmdp->cmd_gtgtp,
10156fd12ef3Slh 	    spktp->pkt_time, polled, NULL);
1016507c3241Smlf 
1017507c3241Smlf 	/* see if pkt was not accepted */
1018507c3241Smlf 
1019507c3241Smlf 	if (rc != TRAN_ACCEPT)
1020507c3241Smlf 		return (rc);
1021507c3241Smlf 
1022507c3241Smlf 	return (rc);
1023507c3241Smlf }
1024507c3241Smlf 
1025507c3241Smlf 
1026507c3241Smlf /*
1027507c3241Smlf  *
1028507c3241Smlf  * GHD packet complete callback
1029507c3241Smlf  *
1030507c3241Smlf  */
1031507c3241Smlf /* ARGSUSED */
1032507c3241Smlf static void
atapi_complete(ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp,int do_callback)1033507c3241Smlf atapi_complete(
1034507c3241Smlf 	ata_drv_t *ata_drvp,
1035507c3241Smlf 	ata_pkt_t *ata_pktp,
1036507c3241Smlf 	int do_callback)
1037507c3241Smlf {
1038507c3241Smlf 	struct scsi_pkt *spktp = APKT2SPKT(ata_pktp);
1039507c3241Smlf 	struct scsi_status *scsi_stat = (struct scsi_status *)spktp->pkt_scbp;
1040507c3241Smlf 
1041507c3241Smlf 	ADBG_TRACE(("atapi_complete entered\n"));
1042507c3241Smlf 	ADBG_TRANSPORT(("atapi_complete: pkt = 0x%p\n", ata_pktp));
1043507c3241Smlf 
1044507c3241Smlf 	/* update resid */
1045507c3241Smlf 
1046507c3241Smlf 	spktp->pkt_resid = ata_pktp->ap_resid;
1047507c3241Smlf 
1048507c3241Smlf 	if (ata_pktp->ap_flags & AP_SENT_CMD) {
1049507c3241Smlf 		spktp->pkt_state |=
10506fd12ef3Slh 		    STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD;
1051507c3241Smlf 	}
1052507c3241Smlf 	if (ata_pktp->ap_flags & AP_XFERRED_DATA) {
1053507c3241Smlf 		spktp->pkt_state |= STATE_XFERRED_DATA;
1054507c3241Smlf 	}
1055507c3241Smlf 
1056507c3241Smlf 	if (ata_pktp->ap_flags & AP_GOT_STATUS) {
1057507c3241Smlf 		spktp->pkt_state |= STATE_GOT_STATUS;
1058507c3241Smlf 	}
1059507c3241Smlf 
1060507c3241Smlf 	/* check for fatal errors */
1061507c3241Smlf 
1062507c3241Smlf 	if (ata_pktp->ap_flags & AP_TRAN_ERROR) {
1063507c3241Smlf 		spktp->pkt_reason = CMD_TRAN_ERR;
1064507c3241Smlf 	} else if (ata_pktp->ap_flags & AP_BUS_RESET) {
1065507c3241Smlf 		spktp->pkt_reason = CMD_RESET;
1066507c3241Smlf 		spktp->pkt_statistics |= STAT_BUS_RESET;
1067507c3241Smlf 	} else if (ata_pktp->ap_flags & AP_DEV_RESET) {
1068507c3241Smlf 		spktp->pkt_reason = CMD_RESET;
1069507c3241Smlf 		spktp->pkt_statistics |= STAT_DEV_RESET;
1070507c3241Smlf 	} else if (ata_pktp->ap_flags & AP_ABORT) {
1071507c3241Smlf 		spktp->pkt_reason = CMD_ABORTED;
1072507c3241Smlf 		spktp->pkt_statistics |= STAT_ABORTED;
1073507c3241Smlf 	} else if (ata_pktp->ap_flags & AP_TIMEOUT) {
1074507c3241Smlf 		spktp->pkt_reason = CMD_TIMEOUT;
1075507c3241Smlf 		spktp->pkt_statistics |= STAT_TIMEOUT;
1076507c3241Smlf 	} else {
1077507c3241Smlf 		spktp->pkt_reason = CMD_CMPLT;
1078507c3241Smlf 	}
1079507c3241Smlf 
1080507c3241Smlf 	/* non-fatal errors */
1081507c3241Smlf 
1082507c3241Smlf 	if (ata_pktp->ap_flags & AP_ERROR)
1083507c3241Smlf 		scsi_stat->sts_chk = 1;
1084507c3241Smlf 	else
1085507c3241Smlf 		scsi_stat->sts_chk = 0;
1086507c3241Smlf 
1087507c3241Smlf 	if (ata_pktp->ap_flags & AP_ARQ_ERROR) {
1088507c3241Smlf 		ADBG_ARQ(("atapi_complete ARQ error 0x%p\n", ata_pktp));
1089507c3241Smlf 		spktp->pkt_reason = CMD_TRAN_ERR;
1090507c3241Smlf 
1091507c3241Smlf 	} else if (ata_pktp->ap_flags & AP_ARQ_OKAY) {
1092507c3241Smlf 		static struct scsi_status zero_scsi_status = { 0 };
1093507c3241Smlf 		struct scsi_arq_status *arqp;
1094507c3241Smlf 
1095507c3241Smlf 		ADBG_ARQ(("atapi_complete ARQ okay 0x%p\n", ata_pktp));
1096507c3241Smlf 		spktp->pkt_state |= STATE_ARQ_DONE;
1097507c3241Smlf 		arqp = ata_pktp->ap_scbp;
1098507c3241Smlf 		arqp->sts_rqpkt_reason = CMD_CMPLT;
1099507c3241Smlf 		arqp->sts_rqpkt_state = STATE_XFERRED_DATA;
1100507c3241Smlf 		arqp->sts_rqpkt_status = zero_scsi_status;
1101507c3241Smlf 		arqp->sts_rqpkt_resid = 0;
1102507c3241Smlf 		arqp->sts_rqpkt_statistics = 0;
1103507c3241Smlf 
1104507c3241Smlf 	}
1105507c3241Smlf 
1106507c3241Smlf 	ADBG_TRANSPORT(("atapi_complete: reason = 0x%x stats = 0x%x "
1107507c3241Smlf 	    "sts_chk = %d\n", spktp->pkt_reason, spktp->pkt_statistics,
1108507c3241Smlf 	    scsi_stat->sts_chk));
1109507c3241Smlf 
1110507c3241Smlf 	if (do_callback && (spktp->pkt_comp))
1111507c3241Smlf 		(*spktp->pkt_comp)(spktp);
1112507c3241Smlf }
1113507c3241Smlf 
1114507c3241Smlf 
1115507c3241Smlf 
1116507c3241Smlf /*
1117507c3241Smlf  * Update the IDENTIFY PACKET DEVICE info
1118507c3241Smlf  */
1119507c3241Smlf 
1120507c3241Smlf static int
atapi_id_update(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)1121507c3241Smlf atapi_id_update(
1122507c3241Smlf 	ata_ctl_t	*ata_ctlp,
1123507c3241Smlf 	ata_drv_t	*ata_drvp,
1124507c3241Smlf 	ata_pkt_t	*ata_pktp)
1125507c3241Smlf {
1126507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
1127507c3241Smlf 	caddr_t		 ioaddr1 = ata_ctlp->ac_ioaddr1;
1128507c3241Smlf 	ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
1129507c3241Smlf 	caddr_t		 ioaddr2 = ata_ctlp->ac_ioaddr2;
1130c8531848Syt 	struct ata_id	*aidp;
1131507c3241Smlf 	int	rc;
1132507c3241Smlf 
1133507c3241Smlf 	/*
1134507c3241Smlf 	 * select the appropriate drive and LUN
1135507c3241Smlf 	 */
1136507c3241Smlf 	ddi_put8(io_hdl1, (uchar_t *)ioaddr1 + AT_DRVHD,
11376fd12ef3Slh 	    ata_drvp->ad_drive_bits);
11389f49ae27Smlf 	ata_nsecwait(400);
1139507c3241Smlf 
1140507c3241Smlf 	/*
1141507c3241Smlf 	 * make certain the drive is selected, and wait for not busy
1142507c3241Smlf 	 */
1143507c3241Smlf 	if (!ata_wait(io_hdl2, ioaddr2, ATS_DRDY, ATS_BSY, 5 * 1000000)) {
1144507c3241Smlf 		ADBG_ERROR(("atapi_id_update: select failed\n"));
1145c8531848Syt 		if (ata_pktp != NULL)
1146c8531848Syt 			ata_pktp->ap_flags |= AP_ERROR;
1147507c3241Smlf 		return (ATA_FSM_RC_FINI);
1148507c3241Smlf 	}
1149507c3241Smlf 
1150c8531848Syt 	if (ata_pktp != NULL)
1151c8531848Syt 		aidp = (struct ata_id *)ata_pktp->ap_v_addr;
1152c8531848Syt 	else
1153c8531848Syt 		aidp = &ata_drvp->ad_id;
1154c8531848Syt 
1155507c3241Smlf 	rc = atapi_id(ata_ctlp->ac_iohandle1, ata_ctlp->ac_ioaddr1,
1156c8531848Syt 	    ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2, aidp);
115762c8caf3SAda 	if (rc) {
115862c8caf3SAda 		swab(aidp->ai_drvser, aidp->ai_drvser,
115962c8caf3SAda 		    sizeof (aidp->ai_drvser));
116062c8caf3SAda 		swab(aidp->ai_fw, aidp->ai_fw,
116162c8caf3SAda 		    sizeof (aidp->ai_fw));
116262c8caf3SAda 		swab(aidp->ai_model, aidp->ai_model,
116362c8caf3SAda 		    sizeof (aidp->ai_model));
116462c8caf3SAda 	}
1165c8531848Syt 
1166c8531848Syt 	if (ata_pktp == NULL)
1167c8531848Syt 		return (ATA_FSM_RC_FINI);
1168507c3241Smlf 
1169507c3241Smlf 	if (!rc) {
1170507c3241Smlf 		ata_pktp->ap_flags |= AP_ERROR;
1171507c3241Smlf 	} else {
1172507c3241Smlf 		ata_pktp->ap_flags |= AP_XFERRED_DATA;
1173507c3241Smlf 	}
1174507c3241Smlf 	return (ATA_FSM_RC_FINI);
1175507c3241Smlf }
1176507c3241Smlf 
1177507c3241Smlf 
1178507c3241Smlf 
1179507c3241Smlf /*
1180507c3241Smlf  * Both drives on the controller share a common pkt to do
1181507c3241Smlf  * ARQ processing. Therefore the pkt is only partially
1182507c3241Smlf  * initialized here. The rest of initialization occurs
1183507c3241Smlf  * just before starting the ARQ pkt when an error is
1184507c3241Smlf  * detected.
1185507c3241Smlf  */
1186507c3241Smlf 
1187507c3241Smlf void
atapi_init_arq(ata_ctl_t * ata_ctlp)1188507c3241Smlf atapi_init_arq(
1189507c3241Smlf 	ata_ctl_t *ata_ctlp)
1190507c3241Smlf {
1191507c3241Smlf 	ata_pkt_t *arq_pktp = ata_ctlp->ac_arq_pktp;
1192507c3241Smlf 
1193507c3241Smlf 	arq_pktp->ap_cdbp = ata_ctlp->ac_arq_cdb;
1194507c3241Smlf 	arq_pktp->ap_cdb_len = sizeof (ata_ctlp->ac_arq_cdb);
1195507c3241Smlf 	arq_pktp->ap_start = atapi_fsm_start;
1196507c3241Smlf 	arq_pktp->ap_intr = atapi_fsm_intr;
1197507c3241Smlf 	arq_pktp->ap_complete = atapi_complete;
1198507c3241Smlf 	arq_pktp->ap_flags = AP_ATAPI;
1199507c3241Smlf 	arq_pktp->ap_cmd = ATC_PACKET;
1200507c3241Smlf 
1201507c3241Smlf 	ata_ctlp->ac_arq_cdb[0] = SCMD_REQUEST_SENSE;
1202507c3241Smlf }
12038c97a06bSAda 
12048c97a06bSAda void
atapi_reset_dma_mode(ata_drv_t * ata_drvp,int need_wait)1205fe072f42SAda atapi_reset_dma_mode(ata_drv_t *ata_drvp, int need_wait)
12068c97a06bSAda {
12078c97a06bSAda 	ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
12088c97a06bSAda 
1209fe072f42SAda 	/*
1210fe072f42SAda 	 * Some very old CD-ROM need to wait 500mS to
1211fe072f42SAda 	 * reset the DMA mode, so after reset the DMA
1212fe072f42SAda 	 * mode when resuming, check whether it was
1213fe072f42SAda 	 * enabled on the device, if not, delay 500mS
1214fe072f42SAda 	 * and reset it again.  Then for normal DVD/CD-ROM,
1215fe072f42SAda 	 * no delay will be on resume.
1216fe072f42SAda 	 */
1217fe072f42SAda 	if (need_wait == TRUE)
1218fe072f42SAda 		drv_usecwait(5 * 100000);
12190f1b305eSSeth Goldberg 	ata_reset_dma_mode(ata_drvp);
12208c97a06bSAda 	(void) atapi_id_update(ata_ctlp, ata_drvp, NULL);
12218c97a06bSAda }
1222