507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * CDDL HEADER START
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The contents of this file are subject to the terms of the
9f49ae270d37efd5c5270cb8046b4229b5380021mlf * Common Development and Distribution License (the "License").
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * You may not use this file except in compliance with the License.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * or http://www.opensolaris.org/os/licensing.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * See the License for the specific language governing permissions
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * and limitations under the License.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * When distributing Covered Code, include this CDDL HEADER in each
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If applicable, add the following below this CDDL HEADER, with the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * fields enclosed by brackets "[]" replaced with your own identifying
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * information: Portions Copyright [yyyy] [name of copyright owner]
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * CDDL HEADER END
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
8793b36b40d14ad0a0fecc97738dc118a928f46cNick Todd * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Use is subject to license terms.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Finite State Machines for ATA controller and ATAPI devices
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/types.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include "ata_common.h"
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include "atapi.h"
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Local functions
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int atapi_start_cmd(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void atapi_send_cdb(ata_ctl_t *ata_ctlp, ata_pkt_t *ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void atapi_start_dma(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void atapi_pio_data_in(ata_ctl_t *ata_ctlp, ata_pkt_t *ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void atapi_pio_data_out(ata_ctl_t *ata_ctlp, ata_pkt_t *ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void atapi_status(ata_ctl_t *ata_ctlp, ata_pkt_t *ata_pktp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t status, int dma_complete);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void atapi_fsm_error(ata_ctl_t *ata_ctlp, uchar_t state,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t event);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfatapi_fsm_error(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t state,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t event)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ERROR(("atapi protocol error: 0x%p 0x%x 0x%x\n",
8793b36b40d14ad0a0fecc97738dc118a928f46cNick Todd (void *)ata_ctlp->ac_data, state, event));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * IO CoD DRQ
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * -- --- ---
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 0 0 0 == 0 invalid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 0 0 1 == 1 Data to device
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 0 1 0 == 2 Idle
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 0 1 1 == 3 Send ATAPI CDB to device
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 1 0 0 == 4 invalid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 1 0 1 == 5 Data from device
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 1 1 0 == 6 Status ready
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 1 1 1 == 7 Future use
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Given the current state and the current event this
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * table determines what action to take. Note, in the actual
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * table I've left room for the invalid event codes: 0, 2, and 7.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * +-----------------------------------------------------
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * | Current Event
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * |
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * State | dataout idle cdb datain status
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * | 1 2 3 5 6
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * |-----------------------------------------------------
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * idle | sendcmd sendcmd sendcmd sendcmd sendcmd
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * cmd | * * sendcdb * read-err-code
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * cdb | xfer-out nada nada xfer-in read-err-code
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * datain | * * * xfer-in read-err-code
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * dataout | xfer-out * * * read-err-code
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * DMA | * * * * read-err-code
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfuchar_t atapi_PioAction[ATAPI_NSTATES][ATAPI_NEVENTS] = {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* invalid dataout idle cdb invalid datain status future */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ A_NADA, A_NADA, A_NADA, A_NADA, A_NADA, A_NADA, A_NADA, A_NADA }, /* Idle */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ A_NADA, A_NADA, A_NADA, A_CDB, A_NADA, A_NADA, A_RE, A_NADA }, /* Cmd */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ A_REX, A_OUT, A_NADA, A_NADA, A_IDLE, A_IN, A_RE, A_UNK }, /* Cdb */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ A_REX, A_UNK, A_IDLE, A_UNK, A_IDLE, A_IN, A_RE, A_UNK }, /* DtaIn */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ A_REX, A_OUT, A_IDLE, A_UNK, A_IDLE, A_UNK, A_RE, A_UNK }, /* DtaOut */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ A_REX, A_UNK, A_UNK, A_UNK, A_UNK, A_UNK, A_RE, A_UNK } /* DmaAct */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf};
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Give the current state and the current event this table
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * determines the new state of the device.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * +----------------------------------------------
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * | Current Event
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * |
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * State | dataout idle cdb datain status
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * |----------------------------------------------
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * idle | cmd cmd cmd cmd cmd
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * cmd | * * cdb * *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * cdb | dataout cdb cdb datain (idle)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * datain | * * * datain (idle)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * dataout | dataout * * * (idle)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * DMA | DMA DMA DMA DMA (idle)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Note: the states enclosed in parens "(state)", are the accept states
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * for this FSM. A separate table is used to encode the done
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * states rather than extra state codes.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfuchar_t atapi_PioNextState[ATAPI_NSTATES][ATAPI_NEVENTS] = {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* invalid dataout idle cdb invalid datain status future */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ S_IDLE, S_IDLE, S_IDLE, S_IDLE, S_IDLE, S_IDLE, S_IDLE, S_IDLE}, /* idle */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ S_CDB, S_CDB, S_CDB, S_CDB, S_CDB, S_CDB, S_IDLE, S_X }, /* cmd */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ S_IDLE, S_OUT, S_CDB, S_CDB, S_CDB, S_IN, S_IDLE, S_X }, /* cdb */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ S_IDLE, S_X, S_IN, S_X, S_IN, S_IN, S_IDLE, S_X }, /* datain */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ S_IDLE, S_OUT, S_OUT, S_X, S_OUT, S_X, S_IDLE, S_X }, /* dataout */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ S_IDLE, S_DMA, S_DMA, S_DMA, S_DMA, S_DMA, S_IDLE, S_DMA } /* dmaActv */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf};
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfatapi_start_cmd(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Bug 1256489:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If AC_BSY_WAIT is set, wait for controller to be not busy,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * before issuing a command. If AC_BSY_WAIT is not set,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * skip the wait. This is important for laptops that do
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * suspend/resume but do not correctly wait for the busy bit to
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * drop after a resume.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_timing_flags & AC_BSY_WAIT) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf 0, ATS_BSY, 5000000)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("atapi_start: BSY too long!\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_ERROR;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_BUSY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Select the drive
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, ata_pktp->ap_hd);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * make certain the drive selected
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2, 0, ATS_BSY, 5000000)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ERROR(("atapi_start_cmd: drive select failed\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_BUSY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Always make certain interrupts are enabled. It's been reported
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * (but not confirmed) that some notebook computers don't
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * clear the interrupt disable bit after being resumed. The
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * easiest way to fix this is to always clear the disable bit
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * before every command.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl2, ata_ctlp->ac_devctl, ATDC_D3);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_lcyl, ata_pktp->ap_lwcyl);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_hcyl, ata_pktp->ap_hicyl);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_sect, ata_pktp->ap_sec);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_count, ata_pktp->ap_count);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pktp->ap_pciide_dma) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT((ata_pktp->ap_flags & (AP_READ | AP_WRITE)) != 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * DMA but no Overlap
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_feature, ATF_ATAPI_DMA);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * copy the Scatter/Gather list to the controller's
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Physical Region Descriptor Table
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pciide_dma_setup(ata_ctlp, ata_pktp->ap_sg_list,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_sg_cnt);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * no DMA and no Overlap
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_feature, 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * This next one sets the device in motion
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_cmd, ata_pktp->ap_cmd);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* wait for the busy bit to settle */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!(ata_drvp->ad_flags & AD_NO_CDB_INTR)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the device will send me an interrupt when it's
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ready for the packet
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_OKAY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* else */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If we don't receive an interrupt requesting the scsi CDB,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * we must poll for DRQ, and then send out the CDB.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Wait for DRQ before sending the CDB. Bailout early
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * if an error occurs.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * I'm not certain what the correct timeout should be.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_wait3(io_hdl2, ata_ctlp->ac_ioaddr2,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATS_DRQ, ATS_BSY, /* okay */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATS_ERR, ATS_BSY, /* cmd failed */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATS_DF, ATS_BSY, /* cmd failed */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf 4000000)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* got good status */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_INTR);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("atapi_start_cmd: 0x%x status 0x%x error 0x%x\n",
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_cmd,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_get8(io_hdl2, ata_ctlp->ac_altstatus),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_get8(io_hdl1, ata_ctlp->ac_error)));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_INTR);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Send the SCSI CDB to the ATAPI device
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfatapi_send_cdb(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int padding;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("atapi_send_cdb entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * send the CDB to the drive
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_rep_put16(io_hdl1, (ushort_t *)ata_pktp->ap_cdbp, ata_ctlp->ac_data,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_cdb_len >> 1, DDI_DEV_NO_AUTOINCR);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * pad to ad_cdb_len bytes
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf padding = ata_pktp->ap_cdb_pad;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf while (padding) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put16(io_hdl1, ata_ctlp->ac_data, 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf padding--;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* wait for the busy bit to settle */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#ifdef ATA_DEBUG_XXX
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t *cp = ata_pktp->ap_cdbp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRANSPORT(("\tatapi scsi cmd (%d bytes):\n ",
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_cdb_len));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRANSPORT(("\t\t 0x%x 0x%x 0x%x 0x%x\n",
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cp[0], cp[1], cp[2], cp[3]));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRANSPORT(("\t\t 0x%x 0x%x 0x%x 0x%x\n",
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cp[4], cp[5], cp[6], cp[7]));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRANSPORT(("\t\t 0x%x 0x%x 0x%x 0x%x\n",
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cp[8], cp[9], cp[10], cp[11]));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#endif
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_SENT_CMD;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Start the DMA engine
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* ARGSUSED */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfatapi_start_dma(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t rd_wr;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Determine the direction. This may look backwards
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * but the command bit programmed into the DMA engine
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * specifies the type of operation the engine performs
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * on the PCI bus (not the ATA bus). Therefore when
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * transferring data from the device to system memory, the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * DMA engine performs PCI Write operations.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pktp->ap_flags & AP_READ)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rd_wr = PCIIDE_BMICX_RWCON_WRITE_TO_MEMORY;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rd_wr = PCIIDE_BMICX_RWCON_READ_FROM_MEMORY;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Start the DMA engine
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pciide_dma_start(ata_ctlp, rd_wr);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Transfer the data from the device
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Note: the atapi_pio_data_in() and atapi_pio_data_out() functions
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * are complicated a lot by the requirement to handle an odd byte count.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The only device we've seen which does this is the Hitachi CDR-7730.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * See bug ID 1214595. It's my understanding that Dell stopped shipping
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * that drive after discovering all the problems it caused, so it may
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * be impossible to find one for any sort of regression test.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * In the future, ATAPI tape drives will also probably support odd byte
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * counts so this code will be excersized more often.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfatapi_pio_data_in(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int drive_bytes;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int xfer_bytes;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int xfer_words;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_XFERRED_DATA;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Get the device's byte count for this transfer
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drive_bytes = ((int)ddi_get8(io_hdl1, ata_ctlp->ac_hcyl) << 8)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf + ddi_get8(io_hdl1, ata_ctlp->ac_lcyl);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Determine actual number I'm going to transfer. My
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * buffer might have fewer bytes than what the device
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * expects or handles on each interrupt.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf xfer_bytes = min(ata_pktp->ap_resid, drive_bytes);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(xfer_bytes >= 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Round down my transfer count to whole words so that
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * if the transfer count is odd it's still handled correctly.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf xfer_words = xfer_bytes / 2;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (xfer_words) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int byte_count = xfer_words * 2;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_rep_get16(io_hdl1, (ushort_t *)ata_pktp->ap_v_addr,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_data, xfer_words, DDI_DEV_NO_AUTOINCR);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_v_addr += byte_count;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drive_bytes -= byte_count;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Handle possible odd byte at end. Read a 16-bit
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * word but discard the high-order byte.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (xfer_bytes & 1) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ushort_t tmp_word;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf tmp_word = ddi_get16(io_hdl1, ata_ctlp->ac_data);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *ata_pktp->ap_v_addr++ = tmp_word & 0xff;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drive_bytes -= 2;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_resid -= xfer_bytes;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRANSPORT(("atapi_pio_data_in: read 0x%x bytes\n", xfer_bytes));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Discard any unwanted data.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (drive_bytes > 0) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRANSPORT(("atapi_pio_data_in: dump 0x%x bytes\n",
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drive_bytes));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* rounded up if the drive_bytes count is odd */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (; drive_bytes > 0; drive_bytes -= 2)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ddi_get16(io_hdl1, ata_ctlp->ac_data);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* wait for the busy bit to settle */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Transfer the data to the device
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfatapi_pio_data_out(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int drive_bytes;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int xfer_bytes;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int xfer_words;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_XFERRED_DATA;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Get the device's byte count for this transfer
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drive_bytes = ((int)ddi_get8(io_hdl1, ata_ctlp->ac_hcyl) << 8)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf + ddi_get8(io_hdl1, ata_ctlp->ac_lcyl);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Determine actual number I'm going to transfer. My
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * buffer might have fewer bytes than what the device
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * expects or handles on each interrupt.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf xfer_bytes = min(ata_pktp->ap_resid, drive_bytes);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Round down my transfer count to whole words so that
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * if the transfer count is odd it's handled correctly.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf xfer_words = xfer_bytes / 2;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (xfer_words) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int byte_count = xfer_words * 2;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_rep_put16(io_hdl1, (ushort_t *)ata_pktp->ap_v_addr,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_data, xfer_words, DDI_DEV_NO_AUTOINCR);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_v_addr += byte_count;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If odd byte count, transfer the last
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * byte. Use a tmp so that I don't run off
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the end off the buffer and possibly page
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * fault.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (xfer_bytes & 1) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ushort_t tmp_word;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* grab the last unsigned byte and widen it to 16-bits */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf tmp_word = *ata_pktp->ap_v_addr++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put16(io_hdl1, ata_ctlp->ac_data, tmp_word);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_resid -= xfer_bytes;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRANSPORT(("atapi_pio_data_out: wrote 0x%x bytes\n", xfer_bytes));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* wait for the busy bit to settle */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * check status of completed command
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfatapi_status(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t status,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int dma_completion)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_GOT_STATUS;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (status & (ATS_DF | ATS_ERR)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_ERROR;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pktp->ap_flags & AP_ERROR) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_status = status;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_error = ddi_get8(io_hdl1, ata_ctlp->ac_error);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If the DMA transfer failed leave the resid set to
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the original byte count. The target driver has
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * to do a REQUEST SENSE to get the true residual
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * byte count. Otherwise, it all transferred so update
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the flags and residual byte count.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (dma_completion && !(ata_pktp->ap_flags & AP_TRAN_ERROR)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_XFERRED_DATA;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_resid = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfatapi_device_reset(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* select the drive */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, ata_drvp->ad_drive_bits);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* issue atapi DEVICE RESET */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_cmd, ATC_DEVICE_RESET);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* wait for the busy bit to settle */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Re-select the drive (this is probably only necessary
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * when resetting drive 1).
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, ata_drvp->ad_drive_bits);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* allow the drive the full 6 seconds to respond */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* LINTED */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2, 0, ATS_BSY, 6 * 1000000)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("atapi_device_reset: still busy\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * It's not clear to me what to do at this point,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the drive might be dead or might eventually
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * recover. For now just ignore it and continue
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * to attempt to use the drive.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfvoid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfatapi_fsm_reset(ata_ctl_t *ata_ctlp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int drive;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * reset drive drive 0 and the drive 1
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (drive = 0; drive <= 1; drive++) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp = CTL2DRV(ata_ctlp, drive, 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_drvp && ATAPIDRV(ata_drvp)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_state = S_IDLE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_device_reset(ata_ctlp, ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfatapi_fsm_start(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("atapi_start entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRANSPORT(("atapi_start: pkt = 0x%p\n", ata_pktp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * check for valid state
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_drvp->ad_state != S_IDLE) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ERROR(("atapi_fsm_start not idle 0x%x\n",
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_state));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_BUSY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_state = S_CMD;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = atapi_start_cmd(ata_ctlp, ata_drvp, ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (rc) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_OKAY:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The command started okay. Just return.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_INTR:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Got Command Phase. The upper layer will send
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the cdb by faking an interrupt.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_FINI:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * command completed immediately, stick on done q
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_BUSY:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The command wouldn't start, tell the upper layer to
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * stick this request on the done queue.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_state = S_IDLE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_BUSY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * All interrupts on an ATAPI device come through here.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * This function determines what to do next, based on
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the current state of the request and the drive's current
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * status bits. See the FSM tables at the top of this file.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfatapi_fsm_intr(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t status;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t intr_reason;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t state;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t event;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t action;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * get the prior state
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf state = ata_drvp->ad_state;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If doing DMA, then:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 1. halt the DMA engine
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 2. reset the interrupt and error latches
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 3. reset the drive's IRQ.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * I think the order of these operations must be
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * exactly as listed. Otherwise we the PCI-IDE
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * controller can hang or we can miss the next interrupt
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * edge.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (state) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case S_DMA:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(ata_pktp->ap_pciide_dma == TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Halt the DMA engine. When we reach this point
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * we already know for certain that the device has
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * an interrupt pending since the ata_get_status()
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * function already checked the PCI-IDE interrupt
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * status bit.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pciide_dma_stop(ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*FALLTHRU*/
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case S_IDLE:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case S_CMD:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case S_CDB:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case S_IN:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case S_OUT:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Clear the PCI-IDE latches and the drive's IRQ
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf status = ata_get_status_clear_intr(ata_ctlp, ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * some non-compliant (i.e., NEC) drives don't
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * set ATS_BSY within 400 nsec. and/or don't keep
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * it asserted until they're actually non-busy.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * There's a small window between reading the alt_status
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * and status registers where the drive might "bounce"
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the ATS_BSY bit.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (status & ATS_BSY)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_BUSY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * get the interrupt reason code
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf intr_reason = ddi_get8(io_hdl1, ata_ctlp->ac_count);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * encode the status and interrupt reason bits
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * into an event code which is used to index the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * FSM tables
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf event = ATAPI_EVENT(status, intr_reason);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * determine the action for this event
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf action = atapi_PioAction[state][event];
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * determine the new state
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_state = atapi_PioNextState[state][event];
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (action) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf default:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case A_UNK:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * invalid state
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ??? this shouldn't happen. ???
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * if there's an active command on
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * this device, the pkt timer should eventually clear the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * device. I might try sending a DEVICE-RESET here to speed
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * up the error recovery except that DEVICE-RESET is kind of
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * complicated to implement correctly because if I send a
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * DEVICE-RESET to drive 1 it deselects itself.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("atapi_fsm_intr: Unsupported intr\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case A_NADA:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drv_usecwait(100);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case A_CDB:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * send out atapi pkt
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_send_cdb(ata_ctlp, ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * start the DMA engine if necessary and change
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the state variable to reflect not doing PIO
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pktp->ap_pciide_dma) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_start_dma(ata_ctlp, ata_drvp, ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_state = S_DMA;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case A_IN:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!(ata_pktp->ap_flags & AP_READ)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * maybe this was a spurious interrupt, just
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * spin for a bit and see if the drive
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * recovers
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_fsm_error(ata_ctlp, state, event);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drv_usecwait(100);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * read in the data
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_pktp->ap_pciide_dma) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_pio_data_in(ata_ctlp, ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case A_OUT:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!(ata_pktp->ap_flags & AP_WRITE)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* spin for a bit and see if the drive recovers */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_fsm_error(ata_ctlp, state, event);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drv_usecwait(100);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * send out data
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_pktp->ap_pciide_dma) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_pio_data_out(ata_ctlp, ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case A_IDLE:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The DRQ bit deasserted before or between the data
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * transfer phases.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_drvp->ad_bogus_drq) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_bogus_drq = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_fsm_error(ata_ctlp, state, event);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drv_usecwait(100);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case A_RE:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If we get here, a command has completed!
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * check status of completed command
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_status(ata_ctlp, ata_pktp, status,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (state == S_DMA) ? TRUE : FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_FINI);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case A_REX:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * some NEC drives don't report the right interrupt
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * reason code for the status phase
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_drvp->ad_nec_bad_status) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_nec_bad_status = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_fsm_error(ata_ctlp, state, event);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drv_usecwait(100);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_status(ata_ctlp, ata_pktp, status,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (state == S_DMA) ? TRUE : FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_FINI);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_OKAY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}