xref: /onnv-gate/usr/src/uts/intel/io/dktp/controller/ata/atapi_fsm.c (revision 7632:91aa3d8541b5)
11709Smlf /*
21709Smlf  * CDDL HEADER START
31709Smlf  *
41709Smlf  * The contents of this file are subject to the terms of the
54852Smlf  * 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 /*
23*7632SNick.Todd@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
241709Smlf  * Use is subject to license terms.
251709Smlf  */
261709Smlf 
271709Smlf /*
281709Smlf  * Finite State Machines for ATA controller and ATAPI devices
291709Smlf  */
301709Smlf 
311709Smlf #include <sys/types.h>
321709Smlf 
331709Smlf #include "ata_common.h"
341709Smlf #include "atapi.h"
351709Smlf 
361709Smlf /*
371709Smlf  * Local functions
381709Smlf  */
391709Smlf static	int	atapi_start_cmd(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
401709Smlf 				ata_pkt_t *ata_pktp);
411709Smlf static	void	atapi_send_cdb(ata_ctl_t *ata_ctlp, ata_pkt_t *ata_pktp);
421709Smlf static	void	atapi_start_dma(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
431709Smlf 				ata_pkt_t *ata_pktp);
441709Smlf static	void	atapi_pio_data_in(ata_ctl_t *ata_ctlp, ata_pkt_t *ata_pktp);
451709Smlf static	void	atapi_pio_data_out(ata_ctl_t *ata_ctlp, ata_pkt_t *ata_pktp);
461709Smlf static	void	atapi_status(ata_ctl_t *ata_ctlp, ata_pkt_t *ata_pktp,
471709Smlf 				uchar_t status, int dma_complete);
481709Smlf static	void	atapi_fsm_error(ata_ctl_t *ata_ctlp, uchar_t state,
491709Smlf 				uchar_t event);
501709Smlf 
511709Smlf 
521709Smlf 
531709Smlf 
541709Smlf static void
atapi_fsm_error(ata_ctl_t * ata_ctlp,uchar_t state,uchar_t event)551709Smlf atapi_fsm_error(
561709Smlf 	ata_ctl_t *ata_ctlp,
571709Smlf 	uchar_t	   state,
581709Smlf 	uchar_t	   event)
591709Smlf {
601709Smlf 	ADBG_ERROR(("atapi protocol error: 0x%p 0x%x 0x%x\n",
61*7632SNick.Todd@Sun.COM 	    (void *)ata_ctlp->ac_data, state, event));
621709Smlf }
631709Smlf 
641709Smlf 
651709Smlf /*
661709Smlf  *
671709Smlf  *  IO  CoD  DRQ
681709Smlf  *  --  ---  ---
691709Smlf  *   0    0    0  == 0 invalid
701709Smlf  *   0    0    1  == 1 Data to device
711709Smlf  *   0    1    0  == 2 Idle
721709Smlf  *   0    1    1  == 3 Send ATAPI CDB to device
731709Smlf  *   1    0    0  == 4 invalid
741709Smlf  *   1    0    1  == 5 Data from device
751709Smlf  *   1    1    0  == 6 Status ready
761709Smlf  *   1    1    1  == 7 Future use
771709Smlf  *
781709Smlf  */
791709Smlf 
801709Smlf /*
811709Smlf  * Given the current state and the current event this
821709Smlf  * table determines what action to take. Note, in the actual
831709Smlf  * table I've left room for the invalid event codes: 0, 2, and 7.
841709Smlf  *
851709Smlf  *		+-----------------------------------------------------
861709Smlf  *		|		Current Event
871709Smlf  *		|
881709Smlf  *	State	|	dataout	idle	cdb	datain	status
891709Smlf  *		|	1	2	3	5	6
901709Smlf  *		|-----------------------------------------------------
911709Smlf  *	idle	|	sendcmd	sendcmd	sendcmd	sendcmd	sendcmd
921709Smlf  *	cmd	|	*	 *	sendcdb	*	read-err-code
931709Smlf  *	cdb	|	xfer-out nada	nada	xfer-in read-err-code
941709Smlf  *	datain	|	*	 *	*	xfer-in	read-err-code
951709Smlf  *	dataout	|	xfer-out *	*	*	read-err-code
961709Smlf  *	DMA	|	*	 *	*	*	read-err-code
971709Smlf  *
981709Smlf  */
991709Smlf 
1001709Smlf uchar_t	atapi_PioAction[ATAPI_NSTATES][ATAPI_NEVENTS] = {
1011709Smlf /* invalid dataout idle	  cdb	  invalid datain  status  future */
1021709Smlf { A_NADA, A_NADA, A_NADA, A_NADA, A_NADA, A_NADA, A_NADA, A_NADA }, /* Idle */
1031709Smlf { A_NADA, A_NADA, A_NADA, A_CDB,  A_NADA, A_NADA, A_RE,   A_NADA }, /* Cmd */
1041709Smlf { A_REX,  A_OUT,  A_NADA, A_NADA, A_IDLE, A_IN,   A_RE,   A_UNK  }, /* Cdb */
1051709Smlf { A_REX,  A_UNK,  A_IDLE, A_UNK,  A_IDLE, A_IN,   A_RE,   A_UNK  }, /* DtaIn */
1061709Smlf { A_REX,  A_OUT,  A_IDLE, A_UNK,  A_IDLE, A_UNK,  A_RE,   A_UNK  }, /* DtaOut */
1071709Smlf { A_REX,  A_UNK,  A_UNK,  A_UNK,  A_UNK,  A_UNK,  A_RE,   A_UNK  }  /* DmaAct */
1081709Smlf };
1091709Smlf 
1101709Smlf /*
1111709Smlf  *
1121709Smlf  * Give the current state and the current event this table
1131709Smlf  * determines the new state of the device.
1141709Smlf  *
1151709Smlf  *		+----------------------------------------------
1161709Smlf  *		|		Current Event
1171709Smlf  *		|
1181709Smlf  *	State	|	dataout	idle	cdb	datain	status
1191709Smlf  *		|----------------------------------------------
1201709Smlf  *	idle	|	cmd	cmd	cmd	cmd	cmd
1211709Smlf  *	cmd	|	*	*	cdb	*	*
1221709Smlf  *	cdb	|	dataout	cdb	cdb	datain	(idle)
1231709Smlf  *	datain	|	*	*	*	datain	(idle)
1241709Smlf  *	dataout	|	dataout	*	*	*	(idle)
1251709Smlf  *	DMA	|	DMA	DMA	DMA	DMA	(idle)
1261709Smlf  *
1271709Smlf  *
1281709Smlf  * Note: the states enclosed in parens "(state)", are the accept states
1291709Smlf  * for this FSM. A separate table is used to encode the done
1301709Smlf  * states rather than extra state codes.
1311709Smlf  *
1321709Smlf  */
1331709Smlf 
1341709Smlf uchar_t	atapi_PioNextState[ATAPI_NSTATES][ATAPI_NEVENTS] = {
1351709Smlf /* invalid dataout idle	  cdb	  invalid datain  status  future */
1361709Smlf { S_IDLE, S_IDLE, S_IDLE, S_IDLE, S_IDLE, S_IDLE, S_IDLE, S_IDLE}, /* idle */
1371709Smlf { S_CDB,  S_CDB,  S_CDB,  S_CDB,  S_CDB,  S_CDB,  S_IDLE, S_X   }, /* cmd */
1381709Smlf { S_IDLE, S_OUT,  S_CDB,  S_CDB,  S_CDB,  S_IN,   S_IDLE, S_X   }, /* cdb */
1391709Smlf { S_IDLE, S_X,    S_IN,   S_X,    S_IN,   S_IN,   S_IDLE, S_X   }, /* datain */
1401709Smlf { S_IDLE, S_OUT,  S_OUT,  S_X,    S_OUT,  S_X,    S_IDLE, S_X   }, /* dataout */
1411709Smlf { S_IDLE, S_DMA,  S_DMA,  S_DMA,  S_DMA,  S_DMA,  S_IDLE, S_DMA }  /* dmaActv */
1421709Smlf };
1431709Smlf 
1441709Smlf 
1451709Smlf static int
atapi_start_cmd(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)1461709Smlf atapi_start_cmd(
1471709Smlf 	ata_ctl_t	*ata_ctlp,
1481709Smlf 	ata_drv_t	*ata_drvp,
1491709Smlf 	ata_pkt_t	*ata_pktp)
1501709Smlf {
1511709Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
1521709Smlf 	ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
1531709Smlf 
1541709Smlf 	/*
1551709Smlf 	 * Bug 1256489:
1561709Smlf 	 *
1571709Smlf 	 * If AC_BSY_WAIT is set, wait for controller to be not busy,
1581709Smlf 	 * before issuing a command.  If AC_BSY_WAIT is not set,
1591709Smlf 	 * skip the wait.  This is important for laptops that do
1601709Smlf 	 * suspend/resume but do not correctly wait for the busy bit to
1611709Smlf 	 * drop after a resume.
1621709Smlf 	 */
1631709Smlf 
1641709Smlf 	if (ata_ctlp->ac_timing_flags & AC_BSY_WAIT) {
1651709Smlf 		if (!ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2,
1661709Smlf 			0, ATS_BSY, 5000000)) {
1671709Smlf 			ADBG_WARN(("atapi_start: BSY too long!\n"));
1681709Smlf 			ata_pktp->ap_flags |= AP_ERROR;
1691709Smlf 			return (ATA_FSM_RC_BUSY);
1701709Smlf 		}
1711709Smlf 	}
1721709Smlf 
1731709Smlf 	/*
1741709Smlf 	 * Select the drive
1751709Smlf 	 */
1761709Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, ata_pktp->ap_hd);
1774852Smlf 	ata_nsecwait(400);
1781709Smlf 
1791709Smlf 	/*
1801709Smlf 	 * make certain the drive selected
1811709Smlf 	 */
1821709Smlf 	if (!ata_wait(io_hdl2,  ata_ctlp->ac_ioaddr2, 0, ATS_BSY, 5000000)) {
1831709Smlf 		ADBG_ERROR(("atapi_start_cmd: drive select failed\n"));
1841709Smlf 		return (ATA_FSM_RC_BUSY);
1851709Smlf 	}
1861709Smlf 
1871709Smlf 	/*
1881709Smlf 	 * Always make certain interrupts are enabled. It's been reported
1891709Smlf 	 * (but not confirmed) that some notebook computers don't
1901709Smlf 	 * clear the interrupt disable bit after being resumed. The
1911709Smlf 	 * easiest way to fix this is to always clear the disable bit
1921709Smlf 	 * before every command.
1931709Smlf 	 */
1941709Smlf 	ddi_put8(io_hdl2, ata_ctlp->ac_devctl, ATDC_D3);
1951709Smlf 
1961709Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_lcyl, ata_pktp->ap_lwcyl);
1971709Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_hcyl, ata_pktp->ap_hicyl);
1981709Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_sect, ata_pktp->ap_sec);
1991709Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_count, ata_pktp->ap_count);
2001709Smlf 
2011709Smlf 	if (ata_pktp->ap_pciide_dma) {
2021709Smlf 
2031709Smlf 		ASSERT((ata_pktp->ap_flags & (AP_READ | AP_WRITE)) != 0);
2041709Smlf 
2051709Smlf 		/*
2061709Smlf 		 * DMA but no Overlap
2071709Smlf 		 */
2081709Smlf 		ddi_put8(io_hdl1, ata_ctlp->ac_feature, ATF_ATAPI_DMA);
2091709Smlf 
2101709Smlf 		/*
2111709Smlf 		 * copy the Scatter/Gather list to the controller's
2121709Smlf 		 * Physical Region Descriptor Table
2131709Smlf 		 */
2141709Smlf 		ata_pciide_dma_setup(ata_ctlp, ata_pktp->ap_sg_list,
2151709Smlf 			ata_pktp->ap_sg_cnt);
2161709Smlf 	} else {
2171709Smlf 		/*
2181709Smlf 		 * no DMA and no Overlap
2191709Smlf 		 */
2201709Smlf 		ddi_put8(io_hdl1, ata_ctlp->ac_feature, 0);
2211709Smlf 	}
2221709Smlf 
2231709Smlf 	/*
2241709Smlf 	 * This next one sets the device in motion
2251709Smlf 	 */
2261709Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_cmd, ata_pktp->ap_cmd);
2271709Smlf 
2281709Smlf 	/* wait for the busy bit to settle */
2294852Smlf 	ata_nsecwait(400);
2301709Smlf 
2311709Smlf 	if (!(ata_drvp->ad_flags & AD_NO_CDB_INTR)) {
2321709Smlf 		/*
2331709Smlf 		 * the device will send me an interrupt when it's
2341709Smlf 		 * ready for the packet
2351709Smlf 		 */
2361709Smlf 		return (ATA_FSM_RC_OKAY);
2371709Smlf 	}
2381709Smlf 
2391709Smlf 	/* else */
2401709Smlf 
2411709Smlf 	/*
2421709Smlf 	 * If we don't receive an interrupt requesting the scsi CDB,
2431709Smlf 	 * we must poll for DRQ, and then send out the CDB.
2441709Smlf 	 */
2451709Smlf 
2461709Smlf 	/*
2471709Smlf 	 * Wait for DRQ before sending the CDB. Bailout early
2481709Smlf 	 * if an error occurs.
2491709Smlf 	 *
2501709Smlf 	 * I'm not certain what the correct timeout should be.
2511709Smlf 	 */
2521709Smlf 	if (ata_wait3(io_hdl2, ata_ctlp->ac_ioaddr2,
2531709Smlf 		ATS_DRQ, ATS_BSY, /* okay */
2541709Smlf 		ATS_ERR, ATS_BSY, /* cmd failed */
2551709Smlf 		ATS_DF,  ATS_BSY, /* cmd failed */
2561709Smlf 		4000000)) {
2571709Smlf 		/* got good status */
2581709Smlf 		return (ATA_FSM_RC_INTR);
2591709Smlf 	}
2601709Smlf 
2611709Smlf 	ADBG_WARN(("atapi_start_cmd: 0x%x status 0x%x error 0x%x\n",
2621709Smlf 		ata_pktp->ap_cmd,
2631709Smlf 		ddi_get8(io_hdl2,  ata_ctlp->ac_altstatus),
2641709Smlf 		ddi_get8(io_hdl1, ata_ctlp->ac_error)));
2651709Smlf 
2661709Smlf 	return (ATA_FSM_RC_INTR);
2671709Smlf }
2681709Smlf 
2691709Smlf 
2701709Smlf /*
2711709Smlf  *
2721709Smlf  * Send the SCSI CDB to the ATAPI device
2731709Smlf  *
2741709Smlf  */
2751709Smlf 
2761709Smlf static void
atapi_send_cdb(ata_ctl_t * ata_ctlp,ata_pkt_t * ata_pktp)2771709Smlf atapi_send_cdb(
2781709Smlf 	ata_ctl_t	*ata_ctlp,
2791709Smlf 	ata_pkt_t	*ata_pktp)
2801709Smlf {
2811709Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2821709Smlf 	int		 padding;
2831709Smlf 
2841709Smlf 	ADBG_TRACE(("atapi_send_cdb entered\n"));
2851709Smlf 
2861709Smlf 	/*
2871709Smlf 	 * send the CDB to the drive
2881709Smlf 	 */
2891709Smlf 	ddi_rep_put16(io_hdl1, (ushort_t *)ata_pktp->ap_cdbp, ata_ctlp->ac_data,
2901709Smlf 		ata_pktp->ap_cdb_len >> 1, DDI_DEV_NO_AUTOINCR);
2911709Smlf 
2921709Smlf 	/*
2931709Smlf 	 * pad to ad_cdb_len bytes
2941709Smlf 	 */
2951709Smlf 
2961709Smlf 	padding = ata_pktp->ap_cdb_pad;
2971709Smlf 
2981709Smlf 	while (padding) {
2991709Smlf 		ddi_put16(io_hdl1, ata_ctlp->ac_data, 0);
3001709Smlf 		padding--;
3011709Smlf 	}
3021709Smlf 
3031709Smlf 	/* wait for the busy bit to settle */
3044852Smlf 	ata_nsecwait(400);
3051709Smlf 
3061709Smlf #ifdef ATA_DEBUG_XXX
3071709Smlf 	{
3081709Smlf 		uchar_t	*cp = ata_pktp->ap_cdbp;
3091709Smlf 
3101709Smlf 		ADBG_TRANSPORT(("\tatapi scsi cmd (%d bytes):\n ",
3111709Smlf 				ata_pktp->ap_cdb_len));
3121709Smlf 		ADBG_TRANSPORT(("\t\t 0x%x 0x%x 0x%x 0x%x\n",
3131709Smlf 			cp[0], cp[1], cp[2], cp[3]));
3141709Smlf 		ADBG_TRANSPORT(("\t\t 0x%x 0x%x 0x%x 0x%x\n",
3151709Smlf 			cp[4], cp[5], cp[6], cp[7]));
3161709Smlf 		ADBG_TRANSPORT(("\t\t 0x%x 0x%x 0x%x 0x%x\n",
3171709Smlf 			cp[8], cp[9], cp[10], cp[11]));
3181709Smlf 	}
3191709Smlf #endif
3201709Smlf 
3211709Smlf 	ata_pktp->ap_flags |= AP_SENT_CMD;
3221709Smlf }
3231709Smlf 
3241709Smlf 
3251709Smlf 
3261709Smlf /*
3271709Smlf  * Start the DMA engine
3281709Smlf  */
3291709Smlf 
3301709Smlf /* ARGSUSED */
3311709Smlf static void
atapi_start_dma(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)3321709Smlf atapi_start_dma(
3331709Smlf 	ata_ctl_t	*ata_ctlp,
3341709Smlf 	ata_drv_t	*ata_drvp,
3351709Smlf 	ata_pkt_t	*ata_pktp)
3361709Smlf {
3371709Smlf 	uchar_t		 rd_wr;
3381709Smlf 
3391709Smlf 	/*
3401709Smlf 	 * Determine the direction. This may look backwards
3411709Smlf 	 * but the command bit programmed into the DMA engine
3421709Smlf 	 * specifies the type of operation the engine performs
3431709Smlf 	 * on the PCI bus (not the ATA bus). Therefore when
3441709Smlf 	 * transferring data from the device to system memory, the
3451709Smlf 	 * DMA engine performs PCI Write operations.
3461709Smlf 	 */
3471709Smlf 	if (ata_pktp->ap_flags & AP_READ)
3481709Smlf 		rd_wr = PCIIDE_BMICX_RWCON_WRITE_TO_MEMORY;
3491709Smlf 	else
3501709Smlf 		rd_wr = PCIIDE_BMICX_RWCON_READ_FROM_MEMORY;
3511709Smlf 
3521709Smlf 	/*
3531709Smlf 	 * Start the DMA engine
3541709Smlf 	 */
3551709Smlf 	ata_pciide_dma_start(ata_ctlp, rd_wr);
3561709Smlf }
3571709Smlf 
3581709Smlf 
3591709Smlf 
3601709Smlf /*
3611709Smlf  * Transfer the data from the device
3621709Smlf  *
3631709Smlf  * Note: the atapi_pio_data_in() and atapi_pio_data_out() functions
3641709Smlf  * are complicated a lot by the requirement to handle an odd byte count.
3651709Smlf  * The only device we've seen which does this is the Hitachi CDR-7730.
3661709Smlf  * See bug ID 1214595. It's my understanding that Dell stopped shipping
3671709Smlf  * that drive after discovering all the problems it caused, so it may
3681709Smlf  * be impossible to find one for any sort of regression test.
3691709Smlf  *
3701709Smlf  * In the future, ATAPI tape drives will also probably support odd byte
3711709Smlf  * counts so this code will be excersized more often.
3721709Smlf  *
3731709Smlf  */
3741709Smlf 
3751709Smlf static void
atapi_pio_data_in(ata_ctl_t * ata_ctlp,ata_pkt_t * ata_pktp)3761709Smlf atapi_pio_data_in(
3771709Smlf 	ata_ctl_t	*ata_ctlp,
3781709Smlf 	ata_pkt_t	*ata_pktp)
3791709Smlf {
3801709Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
3811709Smlf 	int		 drive_bytes;
3821709Smlf 	int		 xfer_bytes;
3831709Smlf 	int		 xfer_words;
3841709Smlf 
3851709Smlf 	ata_pktp->ap_flags |= AP_XFERRED_DATA;
3861709Smlf 
3871709Smlf 	/*
3881709Smlf 	 * Get the device's byte count for this transfer
3891709Smlf 	 */
3901709Smlf 	drive_bytes = ((int)ddi_get8(io_hdl1, ata_ctlp->ac_hcyl) << 8)
3911709Smlf 			+ ddi_get8(io_hdl1, ata_ctlp->ac_lcyl);
3921709Smlf 
3931709Smlf 	/*
3941709Smlf 	 * Determine actual number I'm going to transfer. My
3951709Smlf 	 * buffer might have fewer bytes than what the device
3961709Smlf 	 * expects or handles on each interrupt.
3971709Smlf 	 */
3981709Smlf 	xfer_bytes = min(ata_pktp->ap_resid, drive_bytes);
3991709Smlf 
4001709Smlf 	ASSERT(xfer_bytes >= 0);
4011709Smlf 
4021709Smlf 	/*
4031709Smlf 	 * Round down my transfer count to whole words so that
4041709Smlf 	 * if the transfer count is odd it's still handled correctly.
4051709Smlf 	 */
4061709Smlf 	xfer_words = xfer_bytes / 2;
4071709Smlf 
4081709Smlf 	if (xfer_words) {
4091709Smlf 		int	byte_count = xfer_words * 2;
4101709Smlf 
4111709Smlf 		ddi_rep_get16(io_hdl1, (ushort_t *)ata_pktp->ap_v_addr,
4121709Smlf 			ata_ctlp->ac_data, xfer_words, DDI_DEV_NO_AUTOINCR);
4131709Smlf 
4141709Smlf 		ata_pktp->ap_v_addr += byte_count;
4151709Smlf 		drive_bytes -= byte_count;
4161709Smlf 	}
4171709Smlf 
4181709Smlf 	/*
4191709Smlf 	 * Handle possible odd byte at end. Read a 16-bit
4201709Smlf 	 * word but discard the high-order byte.
4211709Smlf 	 */
4221709Smlf 	if (xfer_bytes & 1) {
4231709Smlf 		ushort_t tmp_word;
4241709Smlf 
4251709Smlf 		tmp_word = ddi_get16(io_hdl1, ata_ctlp->ac_data);
4261709Smlf 		*ata_pktp->ap_v_addr++ = tmp_word & 0xff;
4271709Smlf 		drive_bytes -= 2;
4281709Smlf 	}
4291709Smlf 
4301709Smlf 	ata_pktp->ap_resid -= xfer_bytes;
4311709Smlf 
4321709Smlf 	ADBG_TRANSPORT(("atapi_pio_data_in: read 0x%x bytes\n", xfer_bytes));
4331709Smlf 
4341709Smlf 	/*
4351709Smlf 	 * Discard any unwanted data.
4361709Smlf 	 */
4371709Smlf 	if (drive_bytes > 0) {
4381709Smlf 		ADBG_TRANSPORT(("atapi_pio_data_in: dump 0x%x bytes\n",
4391709Smlf 				drive_bytes));
4401709Smlf 
4411709Smlf 		/* rounded up if the drive_bytes count is odd */
4421709Smlf 		for (; drive_bytes > 0; drive_bytes -= 2)
4431709Smlf 			(void) ddi_get16(io_hdl1, ata_ctlp->ac_data);
4441709Smlf 	}
4451709Smlf 
4461709Smlf 	/* wait for the busy bit to settle */
4474852Smlf 	ata_nsecwait(400);
4481709Smlf }
4491709Smlf 
4501709Smlf 
4511709Smlf /*
4521709Smlf  * Transfer the data to the device
4531709Smlf  */
4541709Smlf 
4551709Smlf static void
atapi_pio_data_out(ata_ctl_t * ata_ctlp,ata_pkt_t * ata_pktp)4561709Smlf atapi_pio_data_out(
4571709Smlf 	ata_ctl_t	*ata_ctlp,
4581709Smlf 	ata_pkt_t	*ata_pktp)
4591709Smlf {
4601709Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
4611709Smlf 	int		 drive_bytes;
4621709Smlf 	int		 xfer_bytes;
4631709Smlf 	int		 xfer_words;
4641709Smlf 
4651709Smlf 	ata_pktp->ap_flags |= AP_XFERRED_DATA;
4661709Smlf 
4671709Smlf 	/*
4681709Smlf 	 * Get the device's byte count for this transfer
4691709Smlf 	 */
4701709Smlf 	drive_bytes = ((int)ddi_get8(io_hdl1, ata_ctlp->ac_hcyl) << 8)
4711709Smlf 			+ ddi_get8(io_hdl1, ata_ctlp->ac_lcyl);
4721709Smlf 
4731709Smlf 	/*
4741709Smlf 	 * Determine actual number I'm going to transfer. My
4751709Smlf 	 * buffer might have fewer bytes than what the device
4761709Smlf 	 * expects or handles on each interrupt.
4771709Smlf 	 */
4781709Smlf 	xfer_bytes = min(ata_pktp->ap_resid, drive_bytes);
4791709Smlf 
4801709Smlf 	/*
4811709Smlf 	 * Round down my transfer count to whole words so that
4821709Smlf 	 * if the transfer count is odd it's handled correctly.
4831709Smlf 	 */
4841709Smlf 	xfer_words = xfer_bytes / 2;
4851709Smlf 
4861709Smlf 	if (xfer_words) {
4871709Smlf 		int	byte_count = xfer_words * 2;
4881709Smlf 
4891709Smlf 		ddi_rep_put16(io_hdl1, (ushort_t *)ata_pktp->ap_v_addr,
4901709Smlf 			ata_ctlp->ac_data, xfer_words, DDI_DEV_NO_AUTOINCR);
4911709Smlf 		ata_pktp->ap_v_addr += byte_count;
4921709Smlf 	}
4931709Smlf 
4941709Smlf 	/*
4951709Smlf 	 * If odd byte count, transfer the last
4961709Smlf 	 * byte. Use a tmp so that I don't run off
4971709Smlf 	 * the end off the buffer and possibly page
4981709Smlf 	 * fault.
4991709Smlf 	 */
5001709Smlf 	if (xfer_bytes & 1) {
5011709Smlf 		ushort_t tmp_word;
5021709Smlf 
5031709Smlf 		/* grab the last unsigned byte and widen it to 16-bits */
5041709Smlf 		tmp_word = *ata_pktp->ap_v_addr++;
5051709Smlf 		ddi_put16(io_hdl1, ata_ctlp->ac_data, tmp_word);
5061709Smlf 	}
5071709Smlf 
5081709Smlf 	ata_pktp->ap_resid -= xfer_bytes;
5091709Smlf 
5101709Smlf 	ADBG_TRANSPORT(("atapi_pio_data_out: wrote 0x%x bytes\n", xfer_bytes));
5111709Smlf 
5121709Smlf 	/* wait for the busy bit to settle */
5134852Smlf 	ata_nsecwait(400);
5141709Smlf }
5151709Smlf 
5161709Smlf 
5171709Smlf /*
5181709Smlf  *
5191709Smlf  * check status of completed command
5201709Smlf  *
5211709Smlf  */
5221709Smlf static void
atapi_status(ata_ctl_t * ata_ctlp,ata_pkt_t * ata_pktp,uchar_t status,int dma_completion)5231709Smlf atapi_status(
5241709Smlf 	ata_ctl_t	*ata_ctlp,
5251709Smlf 	ata_pkt_t	*ata_pktp,
5261709Smlf 	uchar_t		 status,
5271709Smlf 	int		 dma_completion)
5281709Smlf {
5291709Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
5301709Smlf 
5311709Smlf 	ata_pktp->ap_flags |= AP_GOT_STATUS;
5321709Smlf 
5331709Smlf 	if (status & (ATS_DF | ATS_ERR)) {
5341709Smlf 		ata_pktp->ap_flags |= AP_ERROR;
5351709Smlf 	}
5361709Smlf 
5371709Smlf 	if (ata_pktp->ap_flags & AP_ERROR) {
5381709Smlf 		ata_pktp->ap_status = status;
5391709Smlf 		ata_pktp->ap_error = ddi_get8(io_hdl1, ata_ctlp->ac_error);
5401709Smlf 	}
5411709Smlf 
5421709Smlf 
5431709Smlf 	/*
5441709Smlf 	 * If the DMA transfer failed leave the resid set to
5451709Smlf 	 * the original byte count. The target driver has
5461709Smlf 	 * to do a REQUEST SENSE to get the true residual
5471709Smlf 	 * byte count. Otherwise, it all transferred so update
5481709Smlf 	 * the flags and residual byte count.
5491709Smlf 	 */
5501709Smlf 	if (dma_completion && !(ata_pktp->ap_flags & AP_TRAN_ERROR)) {
5511709Smlf 		ata_pktp->ap_flags |= AP_XFERRED_DATA;
5521709Smlf 		ata_pktp->ap_resid = 0;
5531709Smlf 	}
5541709Smlf }
5551709Smlf 
5561709Smlf 
5571709Smlf static void
atapi_device_reset(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp)5581709Smlf atapi_device_reset(
5591709Smlf 	ata_ctl_t	*ata_ctlp,
5601709Smlf 	ata_drv_t	*ata_drvp)
5611709Smlf {
5621709Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
5631709Smlf 	ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
5641709Smlf 
5651709Smlf 	/* select the drive */
5661709Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, ata_drvp->ad_drive_bits);
5674852Smlf 	ata_nsecwait(400);
5681709Smlf 
5691709Smlf 	/* issue atapi DEVICE RESET */
5701709Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_cmd, ATC_DEVICE_RESET);
5711709Smlf 
5721709Smlf 	/* wait for the busy bit to settle */
5734852Smlf 	ata_nsecwait(400);
5741709Smlf 
5751709Smlf 	/*
5761709Smlf 	 * Re-select the drive (this is probably only necessary
5771709Smlf 	 * when resetting drive 1).
5781709Smlf 	 */
5791709Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, ata_drvp->ad_drive_bits);
5804852Smlf 	ata_nsecwait(400);
5811709Smlf 
5821709Smlf 	/* allow the drive the full 6 seconds to respond */
5831709Smlf 	/* LINTED */
5841709Smlf 	if (!ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2, 0, ATS_BSY, 6 * 1000000)) {
5851709Smlf 		ADBG_WARN(("atapi_device_reset: still busy\n"));
5861709Smlf 		/*
5871709Smlf 		 * It's not clear to me what to do at this point,
5881709Smlf 		 * the drive might be dead or might eventually
5891709Smlf 		 * recover. For now just ignore it and continue
5901709Smlf 		 * to attempt to use the drive.
5911709Smlf 		 */
5921709Smlf 	}
5931709Smlf }
5941709Smlf 
5951709Smlf 
5961709Smlf 
5971709Smlf void
atapi_fsm_reset(ata_ctl_t * ata_ctlp)5981709Smlf atapi_fsm_reset(ata_ctl_t *ata_ctlp)
5991709Smlf {
6001709Smlf 	ata_drv_t *ata_drvp;
6011709Smlf 	int	   drive;
6021709Smlf 
6031709Smlf 	/*
6041709Smlf 	 * reset drive drive 0 and the drive 1
6051709Smlf 	 */
6061709Smlf 	for (drive = 0; drive <= 1; drive++) {
6071709Smlf 		ata_drvp = CTL2DRV(ata_ctlp, drive, 0);
6081709Smlf 		if (ata_drvp && ATAPIDRV(ata_drvp)) {
6091709Smlf 			ata_drvp->ad_state = S_IDLE;
6101709Smlf 			atapi_device_reset(ata_ctlp, ata_drvp);
6111709Smlf 		}
6121709Smlf 	}
6131709Smlf }
6141709Smlf 
6151709Smlf 
6161709Smlf int
atapi_fsm_start(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)6171709Smlf atapi_fsm_start(
6181709Smlf 	ata_ctl_t	*ata_ctlp,
6191709Smlf 	ata_drv_t	*ata_drvp,
6201709Smlf 	ata_pkt_t	*ata_pktp)
6211709Smlf {
6221709Smlf 	int		 rc;
6231709Smlf 
6241709Smlf 	ADBG_TRACE(("atapi_start entered\n"));
6251709Smlf 	ADBG_TRANSPORT(("atapi_start: pkt = 0x%p\n", ata_pktp));
6261709Smlf 
6271709Smlf 	/*
6281709Smlf 	 * check for valid state
6291709Smlf 	 */
6301709Smlf 	if (ata_drvp->ad_state != S_IDLE) {
6311709Smlf 		ADBG_ERROR(("atapi_fsm_start not idle 0x%x\n",
6321709Smlf 			    ata_drvp->ad_state));
6331709Smlf 		return (ATA_FSM_RC_BUSY);
6341709Smlf 	} else {
6351709Smlf 		ata_drvp->ad_state = S_CMD;
6361709Smlf 	}
6371709Smlf 
6381709Smlf 	rc = atapi_start_cmd(ata_ctlp, ata_drvp, ata_pktp);
6391709Smlf 
6401709Smlf 	switch (rc) {
6411709Smlf 	case ATA_FSM_RC_OKAY:
6421709Smlf 		/*
6431709Smlf 		 * The command started okay. Just return.
6441709Smlf 		 */
6451709Smlf 		break;
6461709Smlf 	case ATA_FSM_RC_INTR:
6471709Smlf 		/*
6481709Smlf 		 * Got Command Phase. The upper layer will send
6491709Smlf 		 * the cdb by faking an interrupt.
6501709Smlf 		 */
6511709Smlf 		break;
6521709Smlf 	case ATA_FSM_RC_FINI:
6531709Smlf 		/*
6541709Smlf 		 * command completed immediately, stick on done q
6551709Smlf 		 */
6561709Smlf 		break;
6571709Smlf 	case ATA_FSM_RC_BUSY:
6581709Smlf 		/*
6591709Smlf 		 * The command wouldn't start, tell the upper layer to
6601709Smlf 		 * stick this request on the done queue.
6611709Smlf 		 */
6621709Smlf 		ata_drvp->ad_state = S_IDLE;
6631709Smlf 		return (ATA_FSM_RC_BUSY);
6641709Smlf 	}
6651709Smlf 	return (rc);
6661709Smlf }
6671709Smlf 
6681709Smlf /*
6691709Smlf  *
6701709Smlf  * All interrupts on an ATAPI device come through here.
6711709Smlf  * This function determines what to do next, based on
6721709Smlf  * the current state of the request and the drive's current
6731709Smlf  * status bits.  See the FSM tables at the top of this file.
6741709Smlf  *
6751709Smlf  */
6761709Smlf 
6771709Smlf int
atapi_fsm_intr(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)6781709Smlf atapi_fsm_intr(
6791709Smlf 	ata_ctl_t	*ata_ctlp,
6801709Smlf 	ata_drv_t	*ata_drvp,
6811709Smlf 	ata_pkt_t	*ata_pktp)
6821709Smlf {
6831709Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
6841709Smlf 	uchar_t		 status;
6851709Smlf 	uchar_t		 intr_reason;
6861709Smlf 	uchar_t		 state;
6871709Smlf 	uchar_t		 event;
6881709Smlf 	uchar_t		 action;
6891709Smlf 
6901709Smlf 
6911709Smlf 	/*
6921709Smlf 	 * get the prior state
6931709Smlf 	 */
6941709Smlf 	state = ata_drvp->ad_state;
6951709Smlf 
6961709Smlf 	/*
6971709Smlf 	 * If doing DMA, then:
6981709Smlf 	 *
6991709Smlf 	 *	1. halt the DMA engine
7001709Smlf 	 *	2. reset the interrupt and error latches
7011709Smlf 	 *	3. reset the drive's IRQ.
7021709Smlf 	 *
7031709Smlf 	 * I think the order of these operations must be
7041709Smlf 	 * exactly as listed. Otherwise we the PCI-IDE
7051709Smlf 	 * controller can hang or we can miss the next interrupt
7061709Smlf 	 * edge.
7071709Smlf 	 *
7081709Smlf 	 */
7091709Smlf 	switch (state) {
7101709Smlf 	case S_DMA:
7111709Smlf 		ASSERT(ata_pktp->ap_pciide_dma == TRUE);
7121709Smlf 		/*
7131709Smlf 		 * Halt the DMA engine. When we reach this point
7141709Smlf 		 * we already know for certain that the device has
7151709Smlf 		 * an interrupt pending since the ata_get_status()
7161709Smlf 		 * function already checked the PCI-IDE interrupt
7171709Smlf 		 * status bit.
7181709Smlf 		 */
7191709Smlf 		ata_pciide_dma_stop(ata_ctlp);
7201709Smlf 		/*FALLTHRU*/
7211709Smlf 	case S_IDLE:
7221709Smlf 	case S_CMD:
7231709Smlf 	case S_CDB:
7241709Smlf 	case S_IN:
7251709Smlf 	case S_OUT:
7261709Smlf 		break;
7271709Smlf 	}
7281709Smlf 
7291709Smlf 
7301709Smlf 	/*
7311709Smlf 	 * Clear the PCI-IDE latches and the drive's IRQ
7321709Smlf 	 */
7331709Smlf 	status = ata_get_status_clear_intr(ata_ctlp, ata_pktp);
7341709Smlf 
7351709Smlf 	/*
7361709Smlf 	 * some non-compliant (i.e., NEC) drives don't
7371709Smlf 	 * set ATS_BSY within 400 nsec. and/or don't keep
7381709Smlf 	 * it asserted until they're actually non-busy.
7391709Smlf 	 * There's a small window between reading the alt_status
7401709Smlf 	 * and status registers where the drive might "bounce"
7411709Smlf 	 * the ATS_BSY bit.
7421709Smlf 	 */
7431709Smlf 	if (status & ATS_BSY)
7441709Smlf 		return (ATA_FSM_RC_BUSY);
7451709Smlf 
7461709Smlf 	/*
7471709Smlf 	 * get the interrupt reason code
7481709Smlf 	 */
7491709Smlf 	intr_reason = ddi_get8(io_hdl1, ata_ctlp->ac_count);
7501709Smlf 
7511709Smlf 	/*
7521709Smlf 	 * encode the status and interrupt reason bits
7531709Smlf 	 * into an event code which is used to index the
7541709Smlf 	 * FSM tables
7551709Smlf 	 */
7561709Smlf 	event = ATAPI_EVENT(status, intr_reason);
7571709Smlf 
7581709Smlf 	/*
7591709Smlf 	 * determine the action for this event
7601709Smlf 	 */
7611709Smlf 	action = atapi_PioAction[state][event];
7621709Smlf 
7631709Smlf 	/*
7641709Smlf 	 * determine the new state
7651709Smlf 	 */
7661709Smlf 	ata_drvp->ad_state = atapi_PioNextState[state][event];
7671709Smlf 
7681709Smlf 	switch (action) {
7691709Smlf 	default:
7701709Smlf 	case A_UNK:
7711709Smlf 		/*
7721709Smlf 		 * invalid state
7731709Smlf 		 */
7741709Smlf /*
7751709Smlf  * ??? this shouldn't happen. ???
7761709Smlf  *	if there's an active command on
7771709Smlf  *	this device, the pkt timer should eventually clear the
7781709Smlf  *	device. I might try sending a DEVICE-RESET here to speed
7791709Smlf  *	up the error recovery except that DEVICE-RESET is kind of
7801709Smlf  *	complicated to implement correctly because if I send a
7811709Smlf  *	DEVICE-RESET to drive 1 it deselects itself.
7821709Smlf  */
7831709Smlf 		ADBG_WARN(("atapi_fsm_intr: Unsupported intr\n"));
7841709Smlf 		break;
7851709Smlf 
7861709Smlf 	case A_NADA:
7871709Smlf 		drv_usecwait(100);
7881709Smlf 		break;
7891709Smlf 
7901709Smlf 	case A_CDB:
7911709Smlf 		/*
7921709Smlf 		 * send out atapi pkt
7931709Smlf 		 */
7941709Smlf 		atapi_send_cdb(ata_ctlp, ata_pktp);
7951709Smlf 
7961709Smlf 		/*
7971709Smlf 		 * start the DMA engine if necessary and change
7981709Smlf 		 * the state variable to reflect not doing PIO
7991709Smlf 		 */
8001709Smlf 		if (ata_pktp->ap_pciide_dma) {
8011709Smlf 			atapi_start_dma(ata_ctlp, ata_drvp, ata_pktp);
8021709Smlf 			ata_drvp->ad_state = S_DMA;
8031709Smlf 		}
8041709Smlf 		break;
8051709Smlf 
8061709Smlf 	case A_IN:
8071709Smlf 		if (!(ata_pktp->ap_flags & AP_READ)) {
8081709Smlf 			/*
8091709Smlf 			 * maybe this was a spurious interrupt, just
8101709Smlf 			 * spin for a bit and see if the drive
8111709Smlf 			 * recovers
8121709Smlf 			 */
8131709Smlf 			atapi_fsm_error(ata_ctlp, state, event);
8141709Smlf 			drv_usecwait(100);
8151709Smlf 			break;
8161709Smlf 		}
8171709Smlf 		/*
8181709Smlf 		 * read in the data
8191709Smlf 		 */
8201709Smlf 		if (!ata_pktp->ap_pciide_dma) {
8211709Smlf 			atapi_pio_data_in(ata_ctlp, ata_pktp);
8221709Smlf 		}
8231709Smlf 		break;
8241709Smlf 
8251709Smlf 	case A_OUT:
8261709Smlf 		if (!(ata_pktp->ap_flags & AP_WRITE)) {
8271709Smlf 			/* spin for a bit and see if the drive recovers */
8281709Smlf 			atapi_fsm_error(ata_ctlp, state, event);
8291709Smlf 			drv_usecwait(100);
8301709Smlf 			break;
8311709Smlf 		}
8321709Smlf 		/*
8331709Smlf 		 * send out data
8341709Smlf 		 */
8351709Smlf 		if (!ata_pktp->ap_pciide_dma) {
8361709Smlf 			atapi_pio_data_out(ata_ctlp, ata_pktp);
8371709Smlf 		}
8381709Smlf 		break;
8391709Smlf 
8401709Smlf 	case A_IDLE:
8411709Smlf 		/*
8421709Smlf 		 * The DRQ bit deasserted before or between the data
8431709Smlf 		 * transfer phases.
8441709Smlf 		 */
8451709Smlf 		if (!ata_drvp->ad_bogus_drq) {
8461709Smlf 			ata_drvp->ad_bogus_drq = TRUE;
8471709Smlf 			atapi_fsm_error(ata_ctlp, state, event);
8481709Smlf 		}
8491709Smlf 		drv_usecwait(100);
8501709Smlf 		break;
8511709Smlf 
8521709Smlf 	case A_RE:
8531709Smlf 		/*
8541709Smlf 		 * If we get here, a command has completed!
8551709Smlf 		 *
8561709Smlf 		 * check status of completed command
8571709Smlf 		 */
8581709Smlf 		atapi_status(ata_ctlp, ata_pktp, status,
8591709Smlf 			(state == S_DMA) ? TRUE : FALSE);
8601709Smlf 
8611709Smlf 		return (ATA_FSM_RC_FINI);
8621709Smlf 
8631709Smlf 	case A_REX:
8641709Smlf 		/*
8651709Smlf 		 * some NEC drives don't report the right interrupt
8661709Smlf 		 * reason code for the status phase
8671709Smlf 		 */
8681709Smlf 		if (!ata_drvp->ad_nec_bad_status) {
8691709Smlf 			ata_drvp->ad_nec_bad_status = TRUE;
8701709Smlf 			atapi_fsm_error(ata_ctlp, state, event);
8711709Smlf 			drv_usecwait(100);
8721709Smlf 		}
8731709Smlf 		atapi_status(ata_ctlp, ata_pktp, status,
8741709Smlf 			(state == S_DMA) ? TRUE : FALSE);
8751709Smlf 		return (ATA_FSM_RC_FINI);
8761709Smlf 
8771709Smlf 	}
8781709Smlf 	return (ATA_FSM_RC_OKAY);
8791709Smlf }
880