xref: /onnv-gate/usr/src/uts/intel/io/dktp/controller/ata/atapi.c (revision 10452:a93f97af18ab)
11709Smlf /*
21709Smlf  * CDDL HEADER START
31709Smlf  *
41709Smlf  * The contents of this file are subject to the terms of the
53446Smrj  * Common Development and Distribution License (the "License").
61709Smlf  * You may not use this file except in compliance with the License.
71709Smlf  *
81709Smlf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91709Smlf  * or http://www.opensolaris.org/os/licensing.
101709Smlf  * See the License for the specific language governing permissions
111709Smlf  * and limitations under the License.
121709Smlf  *
131709Smlf  * When distributing Covered Code, include this CDDL HEADER in each
141709Smlf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151709Smlf  * If applicable, add the following below this CDDL HEADER, with the
161709Smlf  * fields enclosed by brackets "[]" replaced with your own identifying
171709Smlf  * information: Portions Copyright [yyyy] [name of copyright owner]
181709Smlf  *
191709Smlf  * CDDL HEADER END
201709Smlf  */
211709Smlf 
221709Smlf /*
238550SSeth.Goldberg@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
241709Smlf  * Use is subject to license terms.
251709Smlf  */
261709Smlf 
271709Smlf 
281709Smlf #include <sys/types.h>
291709Smlf 
301709Smlf #include "ata_common.h"
311709Smlf #include "atapi.h"
321709Smlf 
331709Smlf /* SCSA entry points */
341709Smlf 
351709Smlf static int atapi_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
361709Smlf     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
371709Smlf static int atapi_tran_tgt_probe(struct scsi_device *sd, int (*callback)(void));
381709Smlf static void atapi_tran_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
391709Smlf     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
401709Smlf static int atapi_tran_abort(struct scsi_address *ap, struct scsi_pkt *spktp);
411709Smlf static int atapi_tran_reset(struct scsi_address *ap, int level);
421709Smlf static int atapi_tran_getcap(struct scsi_address *ap, char *capstr, int whom);
431709Smlf static int atapi_tran_setcap(struct scsi_address *ap, char *capstr,
441709Smlf     int value, int whom);
451709Smlf static struct scsi_pkt	*atapi_tran_init_pkt(struct scsi_address *ap,
461709Smlf     struct scsi_pkt *spktp, struct buf *bp, int cmdlen, int statuslen,
471709Smlf     int tgtlen, int flags, int (*callback)(caddr_t), caddr_t arg);
481709Smlf static void atapi_tran_destroy_pkt(struct scsi_address *ap,
491709Smlf     struct scsi_pkt *spktp);
501709Smlf static void atapi_tran_dmafree(struct scsi_address *ap, struct scsi_pkt *spktp);
511709Smlf static void atapi_tran_sync_pkt(struct scsi_address *ap,
521709Smlf     struct scsi_pkt *spktp);
531709Smlf static int atapi_tran_start(struct scsi_address *ap, struct scsi_pkt *spktp);
541709Smlf 
551709Smlf /*
561709Smlf  * packet callbacks
571709Smlf  */
581709Smlf static void atapi_complete(ata_drv_t *ata_drvp, ata_pkt_t *ata_pktp,
591709Smlf     int do_callback);
601709Smlf static int atapi_id_update(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
611709Smlf     ata_pkt_t *ata_pktp);
621709Smlf 
631709Smlf 
641709Smlf /* external dependencies */
651709Smlf 
661709Smlf char _depends_on[] = "misc/scsi";
671709Smlf 
681709Smlf /*
691709Smlf  * Local static data
701709Smlf  */
711709Smlf 
721709Smlf #if 0
731709Smlf static ddi_dma_lim_t atapi_dma_limits = {
741709Smlf 	0,		/* address low				*/
751709Smlf 	0xffffffffU,	/* address high				*/
761709Smlf 	0,		/* counter max				*/
771709Smlf 	1,		/* burstsize				*/
781709Smlf 	DMA_UNIT_8,	/* minimum xfer				*/
791709Smlf 	0,		/* dma speed				*/
801709Smlf 	(uint_t)DMALIM_VER0,	/* version			*/
811709Smlf 	0xffffffffU,	/* address register			*/
821709Smlf 	0xffffffffU,	/* counter register			*/
831709Smlf 	1,		/* granular				*/
841709Smlf 	1,		/* scatter/gather list length		*/
851709Smlf 	0xffffffffU	/* request size				*/
861709Smlf };
871709Smlf #endif
881709Smlf 
891709Smlf static	int	atapi_use_static_geometry = TRUE;
901709Smlf static	int	atapi_arq_enable = TRUE;
911709Smlf 
921709Smlf 
931709Smlf /*
941709Smlf  *
951709Smlf  * Call SCSA init to initialize the ATAPI half of the driver
961709Smlf  *
971709Smlf  */
981709Smlf 
991709Smlf int
atapi_attach(ata_ctl_t * ata_ctlp)1001709Smlf atapi_attach(ata_ctl_t *ata_ctlp)
1011709Smlf {
1021709Smlf 	dev_info_t	*dip = ata_ctlp->ac_dip;
1031709Smlf 	scsi_hba_tran_t *tran;
1041709Smlf 
1051709Smlf 	ADBG_TRACE(("atapi_init entered\n"));
1061709Smlf 
1071709Smlf 	/* allocate transport structure */
1081709Smlf 
1091709Smlf 	tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP);
1101709Smlf 
1111709Smlf 	if (tran == NULL) {
1121709Smlf 		ADBG_WARN(("atapi_init: scsi_hba_tran_alloc failed\n"));
1131709Smlf 		goto errout;
1141709Smlf 	}
1151709Smlf 
1161709Smlf 	ata_ctlp->ac_atapi_tran = tran;
1171709Smlf 	ata_ctlp->ac_flags |= AC_SCSI_HBA_TRAN_ALLOC;
1181709Smlf 
1191709Smlf 	/* initialize transport structure */
1201709Smlf 
1211709Smlf 	tran->tran_hba_private = ata_ctlp;
1221709Smlf 	tran->tran_tgt_private = NULL;
1231709Smlf 
1241709Smlf 	tran->tran_tgt_init = atapi_tran_tgt_init;
1251709Smlf 	tran->tran_tgt_probe = atapi_tran_tgt_probe;
1261709Smlf 	tran->tran_tgt_free = atapi_tran_tgt_free;
1271709Smlf 	tran->tran_start = atapi_tran_start;
1281709Smlf 	tran->tran_reset = atapi_tran_reset;
1291709Smlf 	tran->tran_abort = atapi_tran_abort;
1301709Smlf 	tran->tran_getcap = atapi_tran_getcap;
1311709Smlf 	tran->tran_setcap = atapi_tran_setcap;
1321709Smlf 	tran->tran_init_pkt = atapi_tran_init_pkt;
1331709Smlf 	tran->tran_destroy_pkt = atapi_tran_destroy_pkt;
1341709Smlf 	tran->tran_dmafree = atapi_tran_dmafree;
1351709Smlf 	tran->tran_sync_pkt = atapi_tran_sync_pkt;
1361709Smlf 
1371709Smlf 	if (scsi_hba_attach_setup(ata_ctlp->ac_dip, &ata_pciide_dma_attr, tran,
1385792Slh195018 	    SCSI_HBA_TRAN_CLONE) != DDI_SUCCESS) {
1391709Smlf 		ADBG_WARN(("atapi_init: scsi_hba_attach_setup failed\n"));
1401709Smlf 		goto errout;
1411709Smlf 	}
1421709Smlf 
1431709Smlf 	ata_ctlp->ac_flags |= AC_SCSI_HBA_ATTACH;
1441709Smlf 
1451709Smlf 	return (TRUE);
1461709Smlf 
1471709Smlf errout:
1481709Smlf 	atapi_detach(ata_ctlp);
1491709Smlf 	return (FALSE);
1501709Smlf }
1511709Smlf 
1521709Smlf 
1531709Smlf /*
1541709Smlf  *
1551709Smlf  * destroy the atapi sub-system
1561709Smlf  *
1571709Smlf  */
1581709Smlf 
1591709Smlf void
atapi_detach(ata_ctl_t * ata_ctlp)1601709Smlf atapi_detach(
1611709Smlf 	ata_ctl_t *ata_ctlp)
1621709Smlf {
1631709Smlf 	ADBG_TRACE(("atapi_detach entered\n"));
1641709Smlf 
1651709Smlf 	if (ata_ctlp->ac_flags & AC_SCSI_HBA_ATTACH)
1663446Smrj 		(void) scsi_hba_detach(ata_ctlp->ac_dip);
1671709Smlf 
1681709Smlf 	if (ata_ctlp->ac_flags & AC_SCSI_HBA_TRAN_ALLOC)
1691709Smlf 		scsi_hba_tran_free(ata_ctlp->ac_atapi_tran);
1701709Smlf }
1711709Smlf 
1721709Smlf 
1731709Smlf 
1741709Smlf /*
1751709Smlf  *
1761709Smlf  * initialize the ATAPI drive's soft-state based on the
1771709Smlf  * response to IDENTIFY PACKET DEVICE command
1781709Smlf  *
1791709Smlf  */
1801709Smlf 
1811709Smlf int
atapi_init_drive(ata_drv_t * ata_drvp)1821709Smlf atapi_init_drive(
1831709Smlf 	ata_drv_t *ata_drvp)
1841709Smlf {
1856412Syt160523 	ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
1866412Syt160523 
1871709Smlf 	ADBG_TRACE(("atapi_init_drive entered\n"));
1881709Smlf 
1891709Smlf 	/* Determine ATAPI CDB size */
1907554SAda.Feng@Sun.COM 	(void) atapi_id_update(ata_ctlp, ata_drvp, NULL);
1911709Smlf 
1921709Smlf 	switch (ata_drvp->ad_id.ai_config & ATAPI_ID_CFG_PKT_SZ) {
1931709Smlf 
1941709Smlf 	case ATAPI_ID_CFG_PKT_12B:
1951709Smlf 		ata_drvp->ad_cdb_len = 12;
1961709Smlf 		break;
1971709Smlf 	case ATAPI_ID_CFG_PKT_16B:
1981709Smlf 		ata_drvp->ad_cdb_len = 16;
1991709Smlf 		break;
2001709Smlf 	default:
2011709Smlf 		ADBG_WARN(("atapi_init_drive: bad pkt size support\n"));
2021709Smlf 		return (FALSE);
2031709Smlf 	}
2041709Smlf 
2051709Smlf 	/* determine if drive gives an intr when it wants the CDB */
2061709Smlf 
2071709Smlf 	if ((ata_drvp->ad_id.ai_config & ATAPI_ID_CFG_DRQ_TYPE) !=
2081709Smlf 	    ATAPI_ID_CFG_DRQ_INTR)
2091709Smlf 		ata_drvp->ad_flags |= AD_NO_CDB_INTR;
2101709Smlf 
2116412Syt160523 	/*
2126412Syt160523 	 * Some devices may have no DMA mode enabled (UDMA or MWDMA)
2136412Syt160523 	 * by default, so here we need check and enable DMA if none
2146412Syt160523 	 * mode is selected.
2156412Syt160523 	 */
2166412Syt160523 	if (ata_set_dma_mode(ata_ctlp, ata_drvp) == TRUE) {
2176412Syt160523 		/* Update the IDENTIFY PACKET DEVICE data */
2186412Syt160523 		(void) atapi_id_update(ata_ctlp, ata_drvp, NULL);
2196412Syt160523 	}
2206412Syt160523 
2211709Smlf 	return (TRUE);
2221709Smlf }
2231709Smlf 
2241709Smlf 
2251709Smlf /*
2261709Smlf  *
2271709Smlf  * destroy an atapi drive
2281709Smlf  *
2291709Smlf  */
2301709Smlf 
2311709Smlf /* ARGSUSED */
2321709Smlf void
atapi_uninit_drive(ata_drv_t * ata_drvp)2331709Smlf atapi_uninit_drive(
2341709Smlf 	ata_drv_t *ata_drvp)
2351709Smlf {
2361709Smlf 	ADBG_TRACE(("atapi_uninit_drive entered\n"));
2371709Smlf }
2381709Smlf 
2391709Smlf /*
2401709Smlf  *
2411709Smlf  * Issue an IDENTIFY PACKET (ATAPI) DEVICE command
2421709Smlf  *
2431709Smlf  */
2441709Smlf 
2451709Smlf 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)2461709Smlf atapi_id(
2471709Smlf 	ddi_acc_handle_t io_hdl1,
2481709Smlf 	caddr_t		 ioaddr1,
2491709Smlf 	ddi_acc_handle_t io_hdl2,
2501709Smlf 	caddr_t		 ioaddr2,
2511709Smlf 	struct ata_id	*ata_idp)
2521709Smlf {
2531709Smlf 	int	rc;
2541709Smlf 
2551709Smlf 	ADBG_TRACE(("atapi_id entered\n"));
2561709Smlf 
2571709Smlf 	rc = ata_id_common(ATC_ID_PACKET_DEVICE, FALSE, io_hdl1, ioaddr1,
2585792Slh195018 	    io_hdl2, ioaddr2, ata_idp);
2591709Smlf 
2601709Smlf 	if (!rc)
2611709Smlf 		return (FALSE);
2621709Smlf 
2631709Smlf 	if ((ata_idp->ai_config & ATAC_ATAPI_TYPE_MASK) != ATAC_ATAPI_TYPE)
2641709Smlf 		return (FALSE);
2651709Smlf 
2661709Smlf 	return (TRUE);
2671709Smlf }
2681709Smlf 
2691709Smlf 
2701709Smlf /*
2711709Smlf  *
2721709Smlf  * Check the device's register block for the ATAPI signature.
2731709Smlf  *
2741709Smlf  * Although the spec says the sector count, sector number and device/head
2751709Smlf  * registers are also part of the signature, for some unknown reason, this
2761709Smlf  * routine only checks the cyl hi and cyl low registers. I'm just
2771709Smlf  * guessing, but it might be because ATA and ATAPI devices return
2781709Smlf  * identical values in those registers and we actually rely on the
2791709Smlf  * IDENTIFY DEVICE and IDENTIFY PACKET DEVICE commands to recognize the
2801709Smlf  * device type.
2811709Smlf  *
2821709Smlf  */
2831709Smlf 
2841709Smlf int
atapi_signature(ddi_acc_handle_t io_hdl,caddr_t ioaddr)2851709Smlf atapi_signature(
2861709Smlf 	ddi_acc_handle_t io_hdl,
2871709Smlf 	caddr_t ioaddr)
2881709Smlf {
2891709Smlf 	int	rc = FALSE;
2901709Smlf 	ADBG_TRACE(("atapi_signature entered\n"));
2911709Smlf 
2921709Smlf 	if (ddi_get8(io_hdl, (uchar_t *)ioaddr + AT_HCYL) == ATAPI_SIG_HI &&
2935792Slh195018 	    ddi_get8(io_hdl, (uchar_t *)ioaddr + AT_LCYL) != ATAPI_SIG_LO)
2941709Smlf 		rc = TRUE;
2951709Smlf 
2961709Smlf 	/*
2971709Smlf 	 * The following is a little bit of bullet proofing.
2981709Smlf 	 *
2991709Smlf 	 * When some drives are configured on a master-only bus they
3001709Smlf 	 * "shadow" their registers for the not-present slave drive.
3011709Smlf 	 * This is bogus and if you're not careful it may cause a
3021709Smlf 	 * master-only drive to be mistakenly recognized as both
3031709Smlf 	 * master and slave. By clearing the signature registers here
3041709Smlf 	 * I can make certain that when ata_drive_type() switches from
3051709Smlf 	 * the master to slave drive that I'll read back non-signature
3061709Smlf 	 * values regardless of whether the master-only drive does
3071709Smlf 	 * the "shadow" register trick. This prevents a bogus
3081709Smlf 	 * IDENTIFY PACKET DEVICE command from being issued which
3091709Smlf 	 * a really bogus master-only drive will return "shadow"
3101709Smlf 	 * data for.
3111709Smlf 	 */
3121709Smlf 	ddi_put8(io_hdl, (uchar_t *)ioaddr + AT_HCYL, 0);
3131709Smlf 	ddi_put8(io_hdl, (uchar_t *)ioaddr + AT_LCYL, 0);
3141709Smlf 
3151709Smlf 	return (rc);
3161709Smlf }
3171709Smlf 
3181709Smlf 
3191709Smlf /*
3201709Smlf  *
3211709Smlf  * SCSA tran_tgt_init entry point
3221709Smlf  *
3231709Smlf  */
3241709Smlf 
3251709Smlf /* ARGSUSED */
3261709Smlf 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)3271709Smlf atapi_tran_tgt_init(
3281709Smlf 	dev_info_t	*hba_dip,
3291709Smlf 	dev_info_t	*tgt_dip,
3301709Smlf 	scsi_hba_tran_t *hba_tran,
3311709Smlf 	struct scsi_device *sd)
3321709Smlf {
3331709Smlf 	gtgt_t	  *gtgtp;	/* GHD's per-target-instance structure */
3341709Smlf 	ata_ctl_t *ata_ctlp;
3351709Smlf 	ata_tgt_t *ata_tgtp;
3361709Smlf 	ata_drv_t *ata_drvp;
3371709Smlf 	struct scsi_address *ap;
3381709Smlf 	int	rc = DDI_SUCCESS;
3391709Smlf 
3401709Smlf 	ADBG_TRACE(("atapi_tran_tgt_init entered\n"));
3411709Smlf 
3421709Smlf 	/*
3431709Smlf 	 * Qualification of targ, lun, and ATAPI device presence
3441709Smlf 	 *  have already been taken care of by ata_bus_ctl
3451709Smlf 	 */
3461709Smlf 
3471709Smlf 	/* store pointer to drive struct in cloned tran struct */
3481709Smlf 
3491709Smlf 	ata_ctlp = TRAN2CTL(hba_tran);
3501709Smlf 	ap = &sd->sd_address;
3511709Smlf 
3521709Smlf 	ata_drvp = CTL2DRV(ata_ctlp, ap->a_target, ap->a_lun);
3531709Smlf 
3541709Smlf 	/*
3551709Smlf 	 * Create the "atapi" property so the target driver knows
3561709Smlf 	 * to use the correct set of SCSI commands
3571709Smlf 	 */
3581709Smlf 	if (!ata_prop_create(tgt_dip, ata_drvp, "atapi")) {
3591709Smlf 		return (DDI_FAILURE);
3601709Smlf 	}
3611709Smlf 
3621709Smlf 	gtgtp = ghd_target_init(hba_dip, tgt_dip, &ata_ctlp->ac_ccc,
3631709Smlf 	    sizeof (ata_tgt_t), ata_ctlp,
3641709Smlf 	    ap->a_target, ap->a_lun);
3651709Smlf 
3661709Smlf 	/* tran_tgt_private points to gtgt_t */
3671709Smlf 	hba_tran->tran_tgt_private = gtgtp;
3681709Smlf 
3691709Smlf 	/* gt_tgt_private points to ata_tgt_t */
3701709Smlf 	ata_tgtp = GTGTP2ATATGTP(gtgtp);
3711709Smlf 
3721709Smlf 	/* initialize the per-target-instance data */
3731709Smlf 	ata_tgtp->at_drvp = ata_drvp;
3741709Smlf 	ata_tgtp->at_dma_attr = ata_pciide_dma_attr;
3751709Smlf 	ata_tgtp->at_dma_attr.dma_attr_maxxfer =
3761709Smlf 	    ata_ctlp->ac_max_transfer << SCTRSHFT;
3771709Smlf 
3781709Smlf 	return (rc);
3791709Smlf }
3801709Smlf 
3811709Smlf 
3821709Smlf /*
3831709Smlf  *
3841709Smlf  * SCSA tran_tgt_probe entry point
3851709Smlf  *
3861709Smlf  */
3871709Smlf 
3881709Smlf static int
atapi_tran_tgt_probe(struct scsi_device * sd,int (* callback)(void))3891709Smlf atapi_tran_tgt_probe(struct scsi_device *sd, int (*callback)(void))
3901709Smlf {
3911709Smlf 	ADBG_TRACE(("atapi_tran_tgt_probe entered\n"));
3921709Smlf 
3931709Smlf 	return (scsi_hba_probe(sd, callback));
3941709Smlf }
3951709Smlf 
3961709Smlf 
3971709Smlf /*
3981709Smlf  *
3991709Smlf  * SCSA tran_tgt_free entry point
4001709Smlf  *
4011709Smlf  */
4021709Smlf 
4031709Smlf /* ARGSUSED */
4041709Smlf 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)4051709Smlf atapi_tran_tgt_free(
4061709Smlf 	dev_info_t	*hba_dip,
4071709Smlf 	dev_info_t	*tgt_dip,
4081709Smlf 	scsi_hba_tran_t	*hba_tran,
4091709Smlf 	struct scsi_device *sd)
4101709Smlf {
4111709Smlf 	ADBG_TRACE(("atapi_tran_tgt_free entered\n"));
4121709Smlf 
4131709Smlf 	ghd_target_free(hba_dip, tgt_dip, &TRAN2ATAP(hba_tran)->ac_ccc,
4145792Slh195018 	    TRAN2GTGTP(hba_tran));
4151709Smlf 	hba_tran->tran_tgt_private = NULL;
4161709Smlf }
4171709Smlf 
4181709Smlf 
4191709Smlf 
4201709Smlf /*
4211709Smlf  *
4221709Smlf  * SCSA tran_abort entry point
4231709Smlf  *
4241709Smlf  */
4251709Smlf 
4261709Smlf /* ARGSUSED */
4271709Smlf static int
atapi_tran_abort(struct scsi_address * ap,struct scsi_pkt * spktp)4281709Smlf atapi_tran_abort(
4291709Smlf 	struct scsi_address *ap,
4301709Smlf 	struct scsi_pkt *spktp)
4311709Smlf {
4321709Smlf 	ADBG_TRACE(("atapi_tran_abort entered\n"));
4331709Smlf 
4341709Smlf 	if (spktp) {
4351709Smlf 		return (ghd_tran_abort(&ADDR2CTL(ap)->ac_ccc, PKTP2GCMDP(spktp),
4365792Slh195018 		    ADDR2GTGTP(ap), NULL));
4371709Smlf 	}
4381709Smlf 
4391709Smlf 	return (ghd_tran_abort_lun(&ADDR2CTL(ap)->ac_ccc, ADDR2GTGTP(ap),
4405792Slh195018 	    NULL));
4411709Smlf }
4421709Smlf 
4431709Smlf 
4441709Smlf /*
4451709Smlf  *
4461709Smlf  * SCSA tran_reset entry point
4471709Smlf  *
4481709Smlf  */
4491709Smlf 
4501709Smlf /* ARGSUSED */
4511709Smlf static int
atapi_tran_reset(struct scsi_address * ap,int level)4521709Smlf atapi_tran_reset(
4531709Smlf 	struct scsi_address *ap,
4541709Smlf 	int level)
4551709Smlf {
4561709Smlf 	ADBG_TRACE(("atapi_tran_reset entered\n"));
4571709Smlf 
4581709Smlf 	if (level == RESET_TARGET)
4591709Smlf 		return (ghd_tran_reset_target(&ADDR2CTL(ap)->ac_ccc,
4601709Smlf 		    ADDR2GTGTP(ap), NULL));
4611709Smlf 	if (level == RESET_ALL)
4621709Smlf 		return (ghd_tran_reset_bus(&ADDR2CTL(ap)->ac_ccc,
4631709Smlf 		    ADDR2GTGTP(ap), NULL));
4641709Smlf 	return (FALSE);
4651709Smlf 
4661709Smlf }
4671709Smlf 
4681709Smlf 
4691709Smlf /*
4701709Smlf  *
4711709Smlf  * SCSA tran_setcap entry point
4721709Smlf  *
4731709Smlf  */
4741709Smlf 
4751709Smlf static int
atapi_tran_setcap(struct scsi_address * ap,char * capstr,int value,int whom)4761709Smlf atapi_tran_setcap(
4771709Smlf 	struct scsi_address *ap,
4781709Smlf 	char *capstr,
4791709Smlf 	int value,
4801709Smlf 	int whom)
4811709Smlf {
4821709Smlf 	gtgt_t	  *gtgtp = ADDR2GTGTP(ap);
4831709Smlf 	ata_tgt_t *tgtp = GTGTP2ATATGTP(gtgtp);
4841709Smlf 
4851709Smlf 	ADBG_TRACE(("atapi_tran_setcap entered\n"));
4861709Smlf 
4871709Smlf 	switch (scsi_hba_lookup_capstr(capstr)) {
4881709Smlf 		case SCSI_CAP_SECTOR_SIZE:
4891709Smlf 			tgtp->at_dma_attr.dma_attr_granular = (uint_t)value;
4901709Smlf 			return (TRUE);
4911709Smlf 
4921709Smlf 		case SCSI_CAP_ARQ:
4931709Smlf 			if (whom) {
4941709Smlf 				tgtp->at_arq = value;
4951709Smlf 				return (TRUE);
4961709Smlf 			}
4971709Smlf 			break;
4981709Smlf 
4991709Smlf 		case SCSI_CAP_TOTAL_SECTORS:
5001709Smlf 			tgtp->at_total_sectors = value;
5011709Smlf 			return (TRUE);
5021709Smlf 	}
5031709Smlf 	return (FALSE);
5041709Smlf }
5051709Smlf 
5061709Smlf 
5071709Smlf /*
5081709Smlf  *
5091709Smlf  * SCSA tran_getcap entry point
5101709Smlf  *
5111709Smlf  */
5121709Smlf 
5131709Smlf static int
atapi_tran_getcap(struct scsi_address * ap,char * capstr,int whom)5141709Smlf atapi_tran_getcap(
5151709Smlf 	struct scsi_address *ap,
5161709Smlf 	char *capstr,
5171709Smlf 	int whom)
5181709Smlf {
5191709Smlf 	struct ata_id	 ata_id;
5201709Smlf 	struct ata_id	*ata_idp;
5211709Smlf 	ata_ctl_t	*ata_ctlp;
5221709Smlf 	ata_drv_t	*ata_drvp;
5231709Smlf 	gtgt_t		*gtgtp;
5241709Smlf 	int		 rval = -1;
5251709Smlf 
5261709Smlf 	ADBG_TRACE(("atapi_tran_getcap entered\n"));
5271709Smlf 
5281709Smlf 	if (capstr == NULL || whom == 0)
5291709Smlf 		return (-1);
5301709Smlf 
5311709Smlf 	ata_ctlp = ADDR2CTL(ap);
5321709Smlf 
5331709Smlf 	switch (scsi_hba_lookup_capstr(capstr)) {
5341709Smlf 	case SCSI_CAP_ARQ:
5351709Smlf 		rval = TRUE;
5361709Smlf 		break;
5371709Smlf 
5381709Smlf 	case SCSI_CAP_INITIATOR_ID:
5391709Smlf 		rval = 7;
5401709Smlf 		break;
5411709Smlf 
5421709Smlf 	case SCSI_CAP_DMA_MAX:
5431709Smlf 		/* XXX - what should the real limit be?? */
5441709Smlf 		/* limit to 64K ??? */
5451709Smlf 		rval = 4096 * (ATA_DMA_NSEGS - 1);
5461709Smlf 		break;
5471709Smlf 
5481709Smlf 	case SCSI_CAP_GEOMETRY:
5491709Smlf 		/* Default geometry */
5501709Smlf 		if (atapi_use_static_geometry) {
5511709Smlf 			rval = ATAPI_HEADS << 16 | ATAPI_SECTORS_PER_TRK;
5521709Smlf 			break;
5531709Smlf 		}
5541709Smlf 
5551709Smlf 		/* this code is currently not used */
5561709Smlf 
5571709Smlf 		ata_drvp = CTL2DRV(ata_ctlp, ap->a_target, ap->a_lun);
5581709Smlf 		gtgtp = ADDR2GTGTP(ap);
5591709Smlf 
5601709Smlf 		/*
5611709Smlf 		 * retrieve the current IDENTIFY PACKET DEVICE info
5621709Smlf 		 */
5631709Smlf 		if (!ata_queue_cmd(atapi_id_update, &ata_id, ata_ctlp,
5645792Slh195018 		    ata_drvp, gtgtp)) {
5651709Smlf 			ADBG_TRACE(("atapi_tran_getcap geometry failed"));
5661709Smlf 			return (0);
5671709Smlf 		}
5681709Smlf 
5691709Smlf 		/*
5701709Smlf 		 * save the new response data
5711709Smlf 		 */
5721709Smlf 		ata_idp = &ata_drvp->ad_id;
5731709Smlf 		*ata_idp = ata_id;
5741709Smlf 
5751709Smlf 		switch ((ata_idp->ai_config >> 8) & 0xf) {
5761709Smlf 		case DTYPE_RODIRECT:
5771709Smlf 			rval = ATAPI_HEADS << 16 | ATAPI_SECTORS_PER_TRK;
5781709Smlf 			break;
5791709Smlf 		case DTYPE_DIRECT:
5801709Smlf 		case DTYPE_OPTICAL:
5811709Smlf 			rval = (ata_idp->ai_curheads << 16) |
5825792Slh195018 			    ata_idp->ai_cursectrk;
5831709Smlf 			break;
5841709Smlf 		default:
5851709Smlf 			rval = 0;
5861709Smlf 		}
5871709Smlf 		break;
5881709Smlf 	}
5891709Smlf 
5901709Smlf 	return (rval);
5911709Smlf }
5921709Smlf 
5931709Smlf 
5941709Smlf 
5951709Smlf /*
5961709Smlf  *
5971709Smlf  * SCSA tran_init_pkt entry point
5981709Smlf  *
5991709Smlf  */
6001709Smlf 
6011709Smlf 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)6021709Smlf atapi_tran_init_pkt(
6031709Smlf 	struct scsi_address *ap,
6041709Smlf 	struct scsi_pkt	*spktp,
6051709Smlf 	struct buf	*bp,
6061709Smlf 	int		 cmdlen,
6071709Smlf 	int		 statuslen,
6081709Smlf 	int		 tgtlen,
6091709Smlf 	int		 flags,
6101709Smlf 	int		(*callback)(caddr_t),
6111709Smlf 	caddr_t		 arg)
6121709Smlf {
6131709Smlf 	gtgt_t		*gtgtp = ADDR2GTGTP(ap);
6141709Smlf 	ata_tgt_t	*ata_tgtp = GTGTP2ATATGTP(gtgtp);
6151709Smlf 	ata_ctl_t	*ata_ctlp = ADDR2CTL(ap);
6161709Smlf 	ata_pkt_t	*ata_pktp;
6171709Smlf 	struct scsi_pkt	*new_spktp;
6181709Smlf 	ddi_dma_attr_t	*sg_attrp;
6191709Smlf 	int		 bytes;
6201709Smlf 
6211709Smlf 	ADBG_TRACE(("atapi_tran_init_pkt entered\n"));
6221709Smlf 
6231709Smlf 
6241709Smlf 	/*
6251709Smlf 	 * Determine whether to do PCI-IDE DMA setup, start out by
6261709Smlf 	 * assuming we're not.
6271709Smlf 	 */
6281709Smlf 	sg_attrp = NULL;
6291709Smlf 
6301709Smlf 	if (bp == NULL) {
6311709Smlf 		/* no data to transfer */
6321709Smlf 		goto skip_dma_setup;
6331709Smlf 	}
6341709Smlf 
6351709Smlf 	if (bp->b_bcount == 0) {
6361709Smlf 		/* no data to transfer */
6371709Smlf 		goto skip_dma_setup;
6381709Smlf 	}
6391709Smlf 
6401709Smlf 	if ((GTGTP2ATADRVP(ADDR2GTGTP(ap))->ad_pciide_dma == ATA_DMA_OFF)) {
6411709Smlf 		goto skip_dma_setup;
6421709Smlf 	}
6431709Smlf 
6441709Smlf 	if (ata_dma_disabled)
6451709Smlf 		goto skip_dma_setup;
6461709Smlf 
6471709Smlf 
6481709Smlf 	/*
6491709Smlf 	 * The PCI-IDE DMA engine is brain-damaged and can't
6501709Smlf 	 * DMA non-aligned buffers.
6511709Smlf 	 */
6521709Smlf 	if (((bp->b_flags & B_PAGEIO) == 0) &&
6531709Smlf 	    ((uintptr_t)bp->b_un.b_addr) & PCIIDE_PRDE_ADDR_MASK) {
6541709Smlf 		/*
6551709Smlf 		 * if the virtual address isn't aligned, then the
6561709Smlf 		 * physical address also isn't aligned.
6571709Smlf 		 */
6581709Smlf 		goto skip_dma_setup;
6591709Smlf 	}
6601709Smlf 
6611709Smlf 	/*
6621709Smlf 	 * It also insists that the byte count must be even.
6631709Smlf 	 */
6641709Smlf 	if (bp->b_bcount & 1) {
6651709Smlf 		/* something odd here */
6661709Smlf 		goto skip_dma_setup;
6671709Smlf 	}
6681709Smlf 
6691709Smlf 	/*
6701709Smlf 	 * Huzza! We're really going to do it
6711709Smlf 	 */
6721709Smlf 	sg_attrp = &ata_tgtp->at_dma_attr;
6731709Smlf 
6741709Smlf 
6751709Smlf skip_dma_setup:
6761709Smlf 
6771709Smlf 	/*
6781709Smlf 	 * Call GHD packet init function
6791709Smlf 	 */
6801709Smlf 
6811709Smlf 	new_spktp = ghd_tran_init_pkt_attr(&ata_ctlp->ac_ccc, ap, spktp, bp,
6825792Slh195018 	    cmdlen, statuslen, tgtlen, flags,
6835792Slh195018 	    callback, arg, sizeof (ata_pkt_t), sg_attrp);
6841709Smlf 
6851709Smlf 	if (new_spktp == NULL)
6861709Smlf 		return (NULL);
6871709Smlf 
6881709Smlf 	ata_pktp = SPKT2APKT(new_spktp);
6891709Smlf 	ata_pktp->ap_cdbp = new_spktp->pkt_cdbp;
6905792Slh195018 	if (statuslen > 255) {
6915792Slh195018 		statuslen = sizeof (struct scsi_arq_status);
6925792Slh195018 	}
6931709Smlf 	ata_pktp->ap_statuslen = (uchar_t)statuslen;
6941709Smlf 
6951709Smlf 	/* reset data direction flags */
6961709Smlf 	if (spktp)
6971709Smlf 		ata_pktp->ap_flags &= ~(AP_READ | AP_WRITE);
6981709Smlf 
6991709Smlf 	/*
7001709Smlf 	 * check for ARQ mode
7011709Smlf 	 */
7021709Smlf 	if (atapi_arq_enable == TRUE &&
7035792Slh195018 	    ata_tgtp->at_arq == TRUE &&
7045792Slh195018 	    ata_pktp->ap_statuslen >= sizeof (struct scsi_arq_status)) {
7051709Smlf 		ADBG_TRACE(("atapi_tran_init_pkt ARQ\n"));
7061709Smlf 		ata_pktp->ap_scbp =
7071709Smlf 		    (struct scsi_arq_status *)new_spktp->pkt_scbp;
7081709Smlf 		ata_pktp->ap_flags |= AP_ARQ_ON_ERROR;
7091709Smlf 	}
7101709Smlf 
7111709Smlf 	/*
7121709Smlf 	 * fill these with zeros for ATA/ATAPI-4 compatibility
7131709Smlf 	 */
7141709Smlf 	ata_pktp->ap_sec = 0;
7151709Smlf 	ata_pktp->ap_count = 0;
7161709Smlf 
7171709Smlf 	if (ata_pktp->ap_sg_cnt) {
7181709Smlf 		ASSERT(bp != NULL);
7191709Smlf 		/* determine direction to program the DMA engine later */
7201709Smlf 		if (bp->b_flags & B_READ) {
7211709Smlf 			ata_pktp->ap_flags |= AP_READ;
7221709Smlf 		} else {
7231709Smlf 			ata_pktp->ap_flags |= AP_WRITE;
7241709Smlf 		}
7251709Smlf 		ata_pktp->ap_pciide_dma = TRUE;
7261709Smlf 		ata_pktp->ap_hicyl = 0;
7271709Smlf 		ata_pktp->ap_lwcyl = 0;
7281709Smlf 		return (new_spktp);
7291709Smlf 	}
7301709Smlf 
7311709Smlf 	/*
7321709Smlf 	 * Since we're not using DMA, we need to map the buffer into
7331709Smlf 	 * kernel address space
7341709Smlf 	 */
7351709Smlf 
7361709Smlf 	ata_pktp->ap_pciide_dma = FALSE;
7371709Smlf 	if (bp && bp->b_bcount) {
7381709Smlf 		/*
7391709Smlf 		 * If this is a fresh request map the buffer and
7401709Smlf 		 * reset the ap_baddr pointer and the current offset
7411709Smlf 		 * and byte count.
7421709Smlf 		 *
7431709Smlf 		 * The ap_boffset is used to set the ap_v_addr ptr at
7441709Smlf 		 * the start of each I/O request.
7451709Smlf 		 *
7461709Smlf 		 * The ap_bcount is used to update ap_boffset when the
7471709Smlf 		 * target driver requests the next segment.
7481709Smlf 		 *
7491709Smlf 		 */
7501709Smlf 		if (cmdlen) {
7511709Smlf 			bp_mapin(bp);
7521709Smlf 			ata_pktp->ap_baddr = bp->b_un.b_addr;
7531709Smlf 			ata_pktp->ap_bcount = 0;
7541709Smlf 			ata_pktp->ap_boffset = 0;
7551709Smlf 		}
7561709Smlf 		ASSERT(ata_pktp->ap_baddr != NULL);
7571709Smlf 
7581709Smlf 		/* determine direction for the PIO FSM */
7591709Smlf 		if (bp->b_flags & B_READ) {
7601709Smlf 			ata_pktp->ap_flags |= AP_READ;
7611709Smlf 		} else {
7621709Smlf 			ata_pktp->ap_flags |= AP_WRITE;
7631709Smlf 		}
7641709Smlf 
7651709Smlf 		/*
7661709Smlf 		 * If the drive has the Single Sector bug, limit
7671709Smlf 		 * the transfer to a single sector. This assumes
7681709Smlf 		 * ATAPI CD drives always use 2k sectors.
7691709Smlf 		 */
7701709Smlf 		if (GTGTP2ATADRVP(ADDR2GTGTP(ap))->ad_flags & AD_1SECTOR) {
7711709Smlf 			size_t resid;
7721709Smlf 			size_t tmp;
7731709Smlf 
7741709Smlf 			/* adjust offset based on prior request */
7751709Smlf 			ata_pktp->ap_boffset += ata_pktp->ap_bcount;
7761709Smlf 
7771709Smlf 			/* compute number of bytes left to transfer */
7781709Smlf 			resid = bp->b_bcount - ata_pktp->ap_boffset;
7791709Smlf 
7801709Smlf 			/* limit the transfer to 2k */
7811709Smlf 			tmp = MIN(2048, resid);
7821709Smlf 			ata_pktp->ap_bcount = tmp;
7831709Smlf 
7841709Smlf 			/* tell target driver how much is left for next time */
7851709Smlf 			new_spktp->pkt_resid = resid - tmp;
7861709Smlf 		} else {
7871709Smlf 			/* do the whole request in one swell foop */
7881709Smlf 			ata_pktp->ap_bcount = bp->b_bcount;
7891709Smlf 			new_spktp->pkt_resid = 0;
7901709Smlf 		}
7911709Smlf 
7921709Smlf 	} else {
7931709Smlf 		ata_pktp->ap_baddr = NULL;
7941709Smlf 		ata_pktp->ap_bcount = 0;
7951709Smlf 		ata_pktp->ap_boffset = 0;
7961709Smlf 	}
7971709Smlf 
7981709Smlf 	/*
7991709Smlf 	 * determine the size of each partial data transfer
8001709Smlf 	 * to/from the drive
8011709Smlf 	 */
8021709Smlf 	bytes = min(ata_pktp->ap_bcount, ATAPI_MAX_BYTES_PER_DRQ);
8031709Smlf 	ata_pktp->ap_hicyl = (uchar_t)(bytes >> 8);
8041709Smlf 	ata_pktp->ap_lwcyl = (uchar_t)bytes;
8051709Smlf 	return (new_spktp);
8061709Smlf }
8071709Smlf 
8081709Smlf 
8091709Smlf /*
8101709Smlf  * GHD ccballoc callback
8111709Smlf  *
8121709Smlf  *	Initializing the ata_pkt, and return the ptr to the gcmd_t to GHD.
8131709Smlf  *
8141709Smlf  */
8151709Smlf 
8161709Smlf /* ARGSUSED */
8171709Smlf int
atapi_ccballoc(gtgt_t * gtgtp,gcmd_t * gcmdp,int cmdlen,int statuslen,int tgtlen,int ccblen)8181709Smlf atapi_ccballoc(
8191709Smlf 	gtgt_t	*gtgtp,
8201709Smlf 	gcmd_t	*gcmdp,
8211709Smlf 	int	 cmdlen,
8221709Smlf 	int	 statuslen,
8231709Smlf 	int	 tgtlen,
8241709Smlf 	int	 ccblen)
8251709Smlf 
8261709Smlf {
8271709Smlf 	ata_drv_t *ata_drvp = GTGTP2ATADRVP(gtgtp);
8281709Smlf 	ata_pkt_t *ata_pktp = GCMD2APKT(gcmdp);
8291709Smlf 
8301709Smlf 	ADBG_TRACE(("atapi_ccballoc entered\n"));
8311709Smlf 
8321709Smlf 	/* set the back ptr from the ata_pkt to the gcmd_t */
8331709Smlf 	ata_pktp->ap_gcmdp = gcmdp;
8341709Smlf 
8351709Smlf 	/* check length of SCSI CDB is not larger than drive expects */
8361709Smlf 
8371709Smlf 	if (cmdlen > ata_drvp->ad_cdb_len) {
8381709Smlf 		ADBG_WARN(("atapi_ccballoc: SCSI CDB too large!\n"));
8391709Smlf 		return (FALSE);
8401709Smlf 	}
8411709Smlf 
8421709Smlf 	/*
8431709Smlf 	 * save length of the SCSI CDB, and calculate CDB padding
8441709Smlf 	 * note that for convenience, padding is expressed in shorts.
8451709Smlf 	 */
8461709Smlf 
8471709Smlf 	ata_pktp->ap_cdb_len = (uchar_t)cmdlen;
8481709Smlf 	ata_pktp->ap_cdb_pad =
8491709Smlf 		((unsigned)(ata_drvp->ad_cdb_len - cmdlen)) >> 1;
8501709Smlf 
8511709Smlf 	/* set up callback functions */
8521709Smlf 
8531709Smlf 	ata_pktp->ap_start = atapi_fsm_start;
8541709Smlf 	ata_pktp->ap_intr = atapi_fsm_intr;
8551709Smlf 	ata_pktp->ap_complete = atapi_complete;
8561709Smlf 
8571709Smlf 	/* set-up for start */
8581709Smlf 
8591709Smlf 	ata_pktp->ap_flags = AP_ATAPI;
8601709Smlf 	ata_pktp->ap_hd = ata_drvp->ad_drive_bits;
8611709Smlf 	ata_pktp->ap_cmd = ATC_PACKET;
8621709Smlf 
8631709Smlf 	return (TRUE);
8641709Smlf }
8651709Smlf 
8661709Smlf 
8671709Smlf 
8681709Smlf /*
8691709Smlf  *
8701709Smlf  * SCSA tran_destroy_pkt entry point
8711709Smlf  *
8721709Smlf  */
8731709Smlf 
8741709Smlf static void
atapi_tran_destroy_pkt(struct scsi_address * ap,struct scsi_pkt * spktp)8751709Smlf atapi_tran_destroy_pkt(
8761709Smlf 	struct scsi_address *ap,
8771709Smlf 	struct scsi_pkt *spktp)
8781709Smlf {
8791709Smlf 	gcmd_t	  *gcmdp = PKTP2GCMDP(spktp);
8801709Smlf 
8811709Smlf 	ADBG_TRACE(("atapi_tran_destroy_pkt entered\n"));
8821709Smlf 
8831709Smlf 	if (gcmdp->cmd_dma_handle != NULL) {
8841709Smlf 		ghd_dmafree_attr(gcmdp);
8851709Smlf 	}
8861709Smlf 
8871709Smlf 	ghd_pktfree(&ADDR2CTL(ap)->ac_ccc, ap, spktp);
8881709Smlf }
8891709Smlf 
8901709Smlf 
8911709Smlf 
8921709Smlf /*
8931709Smlf  *
8941709Smlf  * GHD ccbfree callback function
8951709Smlf  *
8961709Smlf  */
8971709Smlf 
8981709Smlf /* ARGSUSED */
8991709Smlf void
atapi_ccbfree(gcmd_t * gcmdp)9001709Smlf atapi_ccbfree(
9011709Smlf 	gcmd_t *gcmdp)
9021709Smlf {
9031709Smlf 	ADBG_TRACE(("atapi_ccbfree entered\n"));
9041709Smlf 
9051709Smlf 	/* nothing to do */
9061709Smlf }
9071709Smlf 
9081709Smlf 
9091709Smlf /*
9101709Smlf  *
9111709Smlf  * SCSA tran_dmafree entry point
9121709Smlf  *
9131709Smlf  */
9141709Smlf 
9151709Smlf /*ARGSUSED*/
9161709Smlf static void
atapi_tran_dmafree(struct scsi_address * ap,struct scsi_pkt * spktp)9171709Smlf atapi_tran_dmafree(
9181709Smlf 	struct scsi_address *ap,
9191709Smlf 	struct scsi_pkt *spktp)
9201709Smlf {
9211709Smlf 	gcmd_t	  *gcmdp = PKTP2GCMDP(spktp);
9221709Smlf 
9231709Smlf 	ADBG_TRACE(("atapi_tran_dmafree entered\n"));
9241709Smlf 
9251709Smlf 	if (gcmdp->cmd_dma_handle != NULL) {
9261709Smlf 		ghd_dmafree_attr(gcmdp);
9271709Smlf 	}
9281709Smlf }
9291709Smlf 
9301709Smlf 
9311709Smlf 
9321709Smlf /*
9331709Smlf  *
9341709Smlf  * SCSA tran_sync_pkt entry point
9351709Smlf  *
9361709Smlf  */
9371709Smlf 
9381709Smlf /*ARGSUSED*/
9391709Smlf static void
atapi_tran_sync_pkt(struct scsi_address * ap,struct scsi_pkt * spktp)9401709Smlf atapi_tran_sync_pkt(
9411709Smlf 	struct scsi_address *ap,
9421709Smlf 	struct scsi_pkt *spktp)
9431709Smlf {
9441709Smlf 
9451709Smlf 	ADBG_TRACE(("atapi_tran_sync_pkt entered\n"));
9461709Smlf 
9471709Smlf 	if (PKTP2GCMDP(spktp)->cmd_dma_handle != NULL) {
9481709Smlf 		ghd_tran_sync_pkt(ap, spktp);
9491709Smlf 	}
9501709Smlf }
9511709Smlf 
9521709Smlf 
9531709Smlf 
9541709Smlf /*
9551709Smlf  *
9561709Smlf  * SCSA tran_start entry point
9571709Smlf  *
9581709Smlf  */
9591709Smlf 
9601709Smlf /* ARGSUSED */
9611709Smlf static int
atapi_tran_start(struct scsi_address * ap,struct scsi_pkt * spktp)9621709Smlf atapi_tran_start(
9631709Smlf 	struct scsi_address *ap,
9641709Smlf 	struct scsi_pkt *spktp)
9651709Smlf {
9661709Smlf 	ata_pkt_t *ata_pktp = SPKT2APKT(spktp);
9671709Smlf 	ata_drv_t *ata_drvp = APKT2DRV(ata_pktp);
9681709Smlf 	ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
9691709Smlf 	gcmd_t	  *gcmdp = APKT2GCMD(ata_pktp);
9701709Smlf 	int	   polled = FALSE;
9711709Smlf 	int	   rc;
9721709Smlf 
9731709Smlf 	ADBG_TRACE(("atapi_tran_start entered\n"));
9741709Smlf 
9751709Smlf 	/*
9761709Smlf 	 * Basic initialization performed each and every time a
9771709Smlf 	 * scsi_pkt is submitted. A single scsi_pkt may be submitted
9781709Smlf 	 * multiple times so this routine has to be idempotent. One
9791709Smlf 	 * time initializations don't belong here.
9801709Smlf 	 */
9811709Smlf 
9821709Smlf 	/*
9831709Smlf 	 * The ap_v_addr pointer is incremented by the PIO data
9841709Smlf 	 * transfer routine as each word is transferred. Therefore, need
9851709Smlf 	 * to reset ap_v_addr here (rather than atapi_tran_init_pkt())
9861709Smlf 	 * in case the target resubmits the same pkt multiple times
9871709Smlf 	 * (which is permitted by SCSA).
9881709Smlf 	 */
9891709Smlf 	ata_pktp->ap_v_addr = ata_pktp->ap_baddr + ata_pktp->ap_boffset;
9901709Smlf 
9911709Smlf 	/* ap_resid is decremented as the data transfer progresses */
9921709Smlf 	ata_pktp->ap_resid = ata_pktp->ap_bcount;
9931709Smlf 
9941709Smlf 	/* clear error flags */
9951709Smlf 	ata_pktp->ap_flags &= (AP_ATAPI | AP_READ | AP_WRITE | AP_ARQ_ON_ERROR);
9961709Smlf 	spktp->pkt_reason = 0;
9971709Smlf 	spktp->pkt_state = 0;
9981709Smlf 	spktp->pkt_statistics = 0;
9991709Smlf 
10001709Smlf 	/*
10011709Smlf 	 * check for polling pkt
10021709Smlf 	 */
10031709Smlf 	if (spktp->pkt_flags & FLAG_NOINTR) {
10041709Smlf 		polled = TRUE;
10051709Smlf 	}
10061709Smlf 
10071709Smlf #ifdef ___just_ignore_unsupported_flags___
10081709Smlf 	/* driver cannot accept tagged commands */
10091709Smlf 
10101709Smlf 	if (spktp->pkt_flags & (FLAG_HTAG|FLAG_OTAG|FLAG_STAG)) {
10111709Smlf 		spktp->pkt_reason = CMD_TRAN_ERR;
10121709Smlf 		return (TRAN_BADPKT);
10131709Smlf 	}
10141709Smlf #endif
10151709Smlf 
10161709Smlf 	/* call common transport routine */
10171709Smlf 
10181709Smlf 	rc = ghd_transport(&ata_ctlp->ac_ccc, gcmdp, gcmdp->cmd_gtgtp,
10195792Slh195018 	    spktp->pkt_time, polled, NULL);
10201709Smlf 
10211709Smlf 	/* see if pkt was not accepted */
10221709Smlf 
10231709Smlf 	if (rc != TRAN_ACCEPT)
10241709Smlf 		return (rc);
10251709Smlf 
10261709Smlf 	return (rc);
10271709Smlf }
10281709Smlf 
10291709Smlf 
10301709Smlf /*
10311709Smlf  *
10321709Smlf  * GHD packet complete callback
10331709Smlf  *
10341709Smlf  */
10351709Smlf /* ARGSUSED */
10361709Smlf static void
atapi_complete(ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp,int do_callback)10371709Smlf atapi_complete(
10381709Smlf 	ata_drv_t *ata_drvp,
10391709Smlf 	ata_pkt_t *ata_pktp,
10401709Smlf 	int do_callback)
10411709Smlf {
10421709Smlf 	struct scsi_pkt *spktp = APKT2SPKT(ata_pktp);
10431709Smlf 	struct scsi_status *scsi_stat = (struct scsi_status *)spktp->pkt_scbp;
10441709Smlf 
10451709Smlf 	ADBG_TRACE(("atapi_complete entered\n"));
10461709Smlf 	ADBG_TRANSPORT(("atapi_complete: pkt = 0x%p\n", ata_pktp));
10471709Smlf 
10481709Smlf 	/* update resid */
10491709Smlf 
10501709Smlf 	spktp->pkt_resid = ata_pktp->ap_resid;
10511709Smlf 
10521709Smlf 	if (ata_pktp->ap_flags & AP_SENT_CMD) {
10531709Smlf 		spktp->pkt_state |=
10545792Slh195018 		    STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD;
10551709Smlf 	}
10561709Smlf 	if (ata_pktp->ap_flags & AP_XFERRED_DATA) {
10571709Smlf 		spktp->pkt_state |= STATE_XFERRED_DATA;
10581709Smlf 	}
10591709Smlf 
10601709Smlf 	if (ata_pktp->ap_flags & AP_GOT_STATUS) {
10611709Smlf 		spktp->pkt_state |= STATE_GOT_STATUS;
10621709Smlf 	}
10631709Smlf 
10641709Smlf 	/* check for fatal errors */
10651709Smlf 
10661709Smlf 	if (ata_pktp->ap_flags & AP_TRAN_ERROR) {
10671709Smlf 		spktp->pkt_reason = CMD_TRAN_ERR;
10681709Smlf 	} else if (ata_pktp->ap_flags & AP_BUS_RESET) {
10691709Smlf 		spktp->pkt_reason = CMD_RESET;
10701709Smlf 		spktp->pkt_statistics |= STAT_BUS_RESET;
10711709Smlf 	} else if (ata_pktp->ap_flags & AP_DEV_RESET) {
10721709Smlf 		spktp->pkt_reason = CMD_RESET;
10731709Smlf 		spktp->pkt_statistics |= STAT_DEV_RESET;
10741709Smlf 	} else if (ata_pktp->ap_flags & AP_ABORT) {
10751709Smlf 		spktp->pkt_reason = CMD_ABORTED;
10761709Smlf 		spktp->pkt_statistics |= STAT_ABORTED;
10771709Smlf 	} else if (ata_pktp->ap_flags & AP_TIMEOUT) {
10781709Smlf 		spktp->pkt_reason = CMD_TIMEOUT;
10791709Smlf 		spktp->pkt_statistics |= STAT_TIMEOUT;
10801709Smlf 	} else {
10811709Smlf 		spktp->pkt_reason = CMD_CMPLT;
10821709Smlf 	}
10831709Smlf 
10841709Smlf 	/* non-fatal errors */
10851709Smlf 
10861709Smlf 	if (ata_pktp->ap_flags & AP_ERROR)
10871709Smlf 		scsi_stat->sts_chk = 1;
10881709Smlf 	else
10891709Smlf 		scsi_stat->sts_chk = 0;
10901709Smlf 
10911709Smlf 	if (ata_pktp->ap_flags & AP_ARQ_ERROR) {
10921709Smlf 		ADBG_ARQ(("atapi_complete ARQ error 0x%p\n", ata_pktp));
10931709Smlf 		spktp->pkt_reason = CMD_TRAN_ERR;
10941709Smlf 
10951709Smlf 	} else if (ata_pktp->ap_flags & AP_ARQ_OKAY) {
10961709Smlf 		static struct scsi_status zero_scsi_status = { 0 };
10971709Smlf 		struct scsi_arq_status *arqp;
10981709Smlf 
10991709Smlf 		ADBG_ARQ(("atapi_complete ARQ okay 0x%p\n", ata_pktp));
11001709Smlf 		spktp->pkt_state |= STATE_ARQ_DONE;
11011709Smlf 		arqp = ata_pktp->ap_scbp;
11021709Smlf 		arqp->sts_rqpkt_reason = CMD_CMPLT;
11031709Smlf 		arqp->sts_rqpkt_state = STATE_XFERRED_DATA;
11041709Smlf 		arqp->sts_rqpkt_status = zero_scsi_status;
11051709Smlf 		arqp->sts_rqpkt_resid = 0;
11061709Smlf 		arqp->sts_rqpkt_statistics = 0;
11071709Smlf 
11081709Smlf 	}
11091709Smlf 
11101709Smlf 	ADBG_TRANSPORT(("atapi_complete: reason = 0x%x stats = 0x%x "
11111709Smlf 	    "sts_chk = %d\n", spktp->pkt_reason, spktp->pkt_statistics,
11121709Smlf 	    scsi_stat->sts_chk));
11131709Smlf 
11141709Smlf 	if (do_callback && (spktp->pkt_comp))
11151709Smlf 		(*spktp->pkt_comp)(spktp);
11161709Smlf }
11171709Smlf 
11181709Smlf 
11191709Smlf 
11201709Smlf /*
11211709Smlf  * Update the IDENTIFY PACKET DEVICE info
11221709Smlf  */
11231709Smlf 
11241709Smlf static int
atapi_id_update(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)11251709Smlf atapi_id_update(
11261709Smlf 	ata_ctl_t	*ata_ctlp,
11271709Smlf 	ata_drv_t	*ata_drvp,
11281709Smlf 	ata_pkt_t	*ata_pktp)
11291709Smlf {
11301709Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
11311709Smlf 	caddr_t		 ioaddr1 = ata_ctlp->ac_ioaddr1;
11321709Smlf 	ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
11331709Smlf 	caddr_t		 ioaddr2 = ata_ctlp->ac_ioaddr2;
11346412Syt160523 	struct ata_id	*aidp;
11351709Smlf 	int	rc;
11361709Smlf 
11371709Smlf 	/*
11381709Smlf 	 * select the appropriate drive and LUN
11391709Smlf 	 */
11401709Smlf 	ddi_put8(io_hdl1, (uchar_t *)ioaddr1 + AT_DRVHD,
11415792Slh195018 	    ata_drvp->ad_drive_bits);
11424852Smlf 	ata_nsecwait(400);
11431709Smlf 
11441709Smlf 	/*
11451709Smlf 	 * make certain the drive is selected, and wait for not busy
11461709Smlf 	 */
11471709Smlf 	if (!ata_wait(io_hdl2, ioaddr2, ATS_DRDY, ATS_BSY, 5 * 1000000)) {
11481709Smlf 		ADBG_ERROR(("atapi_id_update: select failed\n"));
11496412Syt160523 		if (ata_pktp != NULL)
11506412Syt160523 			ata_pktp->ap_flags |= AP_ERROR;
11511709Smlf 		return (ATA_FSM_RC_FINI);
11521709Smlf 	}
11531709Smlf 
11546412Syt160523 	if (ata_pktp != NULL)
11556412Syt160523 		aidp = (struct ata_id *)ata_pktp->ap_v_addr;
11566412Syt160523 	else
11576412Syt160523 		aidp = &ata_drvp->ad_id;
11586412Syt160523 
11591709Smlf 	rc = atapi_id(ata_ctlp->ac_iohandle1, ata_ctlp->ac_ioaddr1,
11606412Syt160523 	    ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2, aidp);
11617554SAda.Feng@Sun.COM 	if (rc) {
11627554SAda.Feng@Sun.COM 		swab(aidp->ai_drvser, aidp->ai_drvser,
11637554SAda.Feng@Sun.COM 		    sizeof (aidp->ai_drvser));
11647554SAda.Feng@Sun.COM 		swab(aidp->ai_fw, aidp->ai_fw,
11657554SAda.Feng@Sun.COM 		    sizeof (aidp->ai_fw));
11667554SAda.Feng@Sun.COM 		swab(aidp->ai_model, aidp->ai_model,
11677554SAda.Feng@Sun.COM 		    sizeof (aidp->ai_model));
11687554SAda.Feng@Sun.COM 	}
11696412Syt160523 
11706412Syt160523 	if (ata_pktp == NULL)
11716412Syt160523 		return (ATA_FSM_RC_FINI);
11721709Smlf 
11731709Smlf 	if (!rc) {
11741709Smlf 		ata_pktp->ap_flags |= AP_ERROR;
11751709Smlf 	} else {
11761709Smlf 		ata_pktp->ap_flags |= AP_XFERRED_DATA;
11771709Smlf 	}
11781709Smlf 	return (ATA_FSM_RC_FINI);
11791709Smlf }
11801709Smlf 
11811709Smlf 
11821709Smlf 
11831709Smlf /*
11841709Smlf  * Both drives on the controller share a common pkt to do
11851709Smlf  * ARQ processing. Therefore the pkt is only partially
11861709Smlf  * initialized here. The rest of initialization occurs
11871709Smlf  * just before starting the ARQ pkt when an error is
11881709Smlf  * detected.
11891709Smlf  */
11901709Smlf 
11911709Smlf void
atapi_init_arq(ata_ctl_t * ata_ctlp)11921709Smlf atapi_init_arq(
11931709Smlf 	ata_ctl_t *ata_ctlp)
11941709Smlf {
11951709Smlf 	ata_pkt_t *arq_pktp = ata_ctlp->ac_arq_pktp;
11961709Smlf 
11971709Smlf 	arq_pktp->ap_cdbp = ata_ctlp->ac_arq_cdb;
11981709Smlf 	arq_pktp->ap_cdb_len = sizeof (ata_ctlp->ac_arq_cdb);
11991709Smlf 	arq_pktp->ap_start = atapi_fsm_start;
12001709Smlf 	arq_pktp->ap_intr = atapi_fsm_intr;
12011709Smlf 	arq_pktp->ap_complete = atapi_complete;
12021709Smlf 	arq_pktp->ap_flags = AP_ATAPI;
12031709Smlf 	arq_pktp->ap_cmd = ATC_PACKET;
12041709Smlf 
12051709Smlf 	ata_ctlp->ac_arq_cdb[0] = SCMD_REQUEST_SENSE;
12061709Smlf }
12077787SAda.Feng@Sun.COM 
12087787SAda.Feng@Sun.COM void
atapi_reset_dma_mode(ata_drv_t * ata_drvp,int need_wait)1209*10452SAda.Feng@Sun.COM atapi_reset_dma_mode(ata_drv_t *ata_drvp, int need_wait)
12107787SAda.Feng@Sun.COM {
12117787SAda.Feng@Sun.COM 	ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
12127787SAda.Feng@Sun.COM 
1213*10452SAda.Feng@Sun.COM 	/*
1214*10452SAda.Feng@Sun.COM 	 * Some very old CD-ROM need to wait 500mS to
1215*10452SAda.Feng@Sun.COM 	 * reset the DMA mode, so after reset the DMA
1216*10452SAda.Feng@Sun.COM 	 * mode when resuming, check whether it was
1217*10452SAda.Feng@Sun.COM 	 * enabled on the device, if not, delay 500mS
1218*10452SAda.Feng@Sun.COM 	 * and reset it again.  Then for normal DVD/CD-ROM,
1219*10452SAda.Feng@Sun.COM 	 * no delay will be on resume.
1220*10452SAda.Feng@Sun.COM 	 */
1221*10452SAda.Feng@Sun.COM 	if (need_wait == TRUE)
1222*10452SAda.Feng@Sun.COM 		drv_usecwait(5 * 100000);
12238550SSeth.Goldberg@Sun.COM 	ata_reset_dma_mode(ata_drvp);
12247787SAda.Feng@Sun.COM 	(void) atapi_id_update(ata_ctlp, ata_drvp, NULL);
12257787SAda.Feng@Sun.COM }
1226