507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * CDDL HEADER START
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The contents of this file are subject to the terms of the
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf * 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/*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Use is subject to license terms.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/types.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/modctl.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/debug.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/promif.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/pci.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/errno.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/open.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/uio.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/cred.h>
9f49ae270d37efd5c5270cb8046b4229b5380021mlf#include <sys/cpu.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include "ata_common.h"
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include "ata_disk.h"
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include "atapi.h"
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include "ata_blacklist.h"
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include "sil3xxx.h"
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Solaris Entry Points.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_bus_ctl(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t o,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *a, void *v);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic uint_t ata_intr(caddr_t arg);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * GHD Entry points
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_get_status(void *hba_handle, void *intr_status);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void ata_process_intr(void *hba_handle, void *intr_status);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_hba_start(void *handle, gcmd_t *gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void ata_hba_complete(void *handle, gcmd_t *gcmdp, int do_callback);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_timeout_func(void *hba_handle, gcmd_t *gcmdp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gtgt_t *gtgtp, gact_t action, int calltype);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Local Function Prototypes
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_prop_lookup_int(dev_t match_dev, dev_info_t *dip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t flags, char *name, int defvalue);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_ctlr_fsm(uchar_t fsm_func, ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp, ata_pkt_t *ata_pktp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int *DoneFlgp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void ata_destroy_controller(dev_info_t *dip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_drive_type(uchar_t drvhd,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl1, caddr_t ioaddr1,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl2, caddr_t ioaddr2,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf struct ata_id *ata_id_bufp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic ata_ctl_t *ata_init_controller(dev_info_t *dip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic ata_drv_t *ata_init_drive(ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t targ, uchar_t lun);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_init_drive_pcidma(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *tdip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_flush_cache(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void ata_init_pciide(dev_info_t *dip, ata_ctl_t *ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_reset_bus(ata_ctl_t *ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_setup_ioaddr(dev_info_t *dip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t *iohandle1, caddr_t *ioaddr1p,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t *iohandle2, caddr_t *ioaddr2p,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t *bm_hdlp, caddr_t *bm_addrp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_software_reset(ata_ctl_t *ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_start_arq(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_strncmp(char *p1, char *p2, int cnt);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void ata_uninit_drive(ata_drv_t *ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_check_pciide_blacklist(dev_info_t *dip, uint_t flags);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_check_revert_to_defaults(ata_drv_t *ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void ata_show_transfer_mode(ata_ctl_t *, ata_drv_t *);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_spec_init_controller(dev_info_t *dip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void ata_init_pm(dev_info_t *);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int ata_suspend(dev_info_t *);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int ata_resume(dev_info_t *);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int ata_power(dev_info_t *, int, int);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int ata_change_power(dev_info_t *, uint8_t);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int ata_is_pci(dev_info_t *);
5fb86bae323519d98a63f5829df4b849f1fe1598mlstatic void ata_disable_DMA(ata_drv_t *ata_drvp);
fe072f421ec51952432306add7d50852ad1921b2Adastatic int ata_check_dma_mode(ata_drv_t *ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Local static data
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void *ata_state;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic tmr_t ata_timer_conf; /* single timeout list for all instances */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ata_watchdog_usec = 100000; /* check timeouts every 100 ms */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ata_hba_start_watchdog = 1000;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ata_process_intr_watchdog = 1000;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ata_reset_bus_watchdog = 1000;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Use local or framework power management
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#ifdef ATA_USE_AUTOPM
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define ATA_BUSY_COMPONENT(d, c) ((void)pm_busy_component(d, c))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define ATA_IDLE_COMPONENT(d, c) ((void)pm_idle_component(d, c))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define ATA_RAISE_POWER(d, c, l) pm_raise_power(d, c, l)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define ATA_LOWER_POWER(d, c, l) pm_lower_power(d, c, l)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#else
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define ATA_BUSY_COMPONENT(d, c)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define ATA_IDLE_COMPONENT(d, c)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define ATA_RAISE_POWER(d, c, l) ata_power(d, c, l)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define ATA_LOWER_POWER(d, c, l) ata_power(d, c, l)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * number of seconds to wait during various operations
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ata_flush_delay = 5 * 1000000;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfuint_t ata_set_feature_wait = 4 * 1000000;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfuint_t ata_flush_cache_wait = 60 * 1000000; /* may take a long time */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Change this for SFF-8070i support. Currently SFF-8070i is
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * using a field in the IDENTIFY PACKET DEVICE response which
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * already seems to be in use by some vendor's drives. I suspect
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * SFF will either move their laslun field or provide a reliable
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * way to validate it.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ata_enable_atapi_luns = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * set this to disable all DMA requests
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ata_dma_disabled = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * set this to TRUE to enable storing the IDENTIFY DEVICE result in the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * "ata" or "atapi" property.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ata_id_debug = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * set this to TRUE to enable logging device-capability data
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ata_capability_data = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * DMA selection message pointers
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfchar *ata_cntrl_DMA_sel_msg;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfchar *ata_dev_DMA_sel_msg;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * bus nexus operations
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic struct bus_ops ata_bus_ops;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic struct bus_ops *scsa_bus_ops_p;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* ARGSUSED */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ddi_get_soft_state(ata_state, getminor(*devp)) == NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ENXIO);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The purpose of this function is to pass the ioaddress of the controller
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * to the caller, specifically used for upgrade from pre-pciide
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * to pciide nodes
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* ARGSUSED */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_read(dev_t dev, struct uio *uio_p, cred_t *cred_p)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf char buf[18];
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf long len;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp = ddi_get_soft_state(ata_state, getminor(dev));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp == NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ENXIO);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) sprintf(buf, "%p\n", (void *) ata_ctlp->ac_ioaddr1);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf len = strlen(buf) - uio_p->uio_offset;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf len = min(uio_p->uio_resid, len);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (len <= 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (uiomove((caddr_t)(buf + uio_p->uio_offset), len,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf UIO_READ, uio_p));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_devo_reset(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *dip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_reset_cmd_t cmd)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int instance;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int i;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int flush_okay;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (cmd != DDI_RESET_FORCE)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf instance = ddi_get_instance(dip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp = ddi_get_soft_state(ata_state, instance);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_ctlp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * reset ATA drives and flush the write cache of any drives
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf flush_okay = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (i = 0; i < ATA_MAXTARG; i++) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((ata_drvp = CTL2DRV(ata_ctlp, i, 0)) == 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Don't revert to defaults for certain IBM drives */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((ata_drvp->ad_flags & AD_DISK) != 0 &&
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ((ata_drvp->ad_flags & AD_NORVRT) == 0)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Enable revert to defaults when reset */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) ata_set_feature(ata_ctlp, ata_drvp,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATSF_ENA_REVPOD, 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * skip flush cache if device type is cdrom
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * notes: the structure definitions for ata_drvp->ad_id are
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * defined for the ATA IDENTIFY_DEVICE, but if AD_ATAPI is set
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the struct holds data for the ATAPI IDENTIFY_PACKET_DEVICE
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!IS_CDROM(ata_drvp)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Try the ATA/ATAPI flush write cache command
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ata_flush_cache(ata_ctlp, ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_flush_cache %s\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf rc ? "okay" : "failed"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!rc)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf flush_okay = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * do something else if flush cache not supported
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * just busy wait if any drive doesn't support FLUSH CACHE
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!flush_okay)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drv_usecwait(ata_flush_delay);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
193974072f41a843678abf5f61979c748687e66bSherry Moore/*
193974072f41a843678abf5f61979c748687e66bSherry Moore * quiesce(9E) entry point.
193974072f41a843678abf5f61979c748687e66bSherry Moore *
193974072f41a843678abf5f61979c748687e66bSherry Moore * This function is called when the system is single-threaded at high
193974072f41a843678abf5f61979c748687e66bSherry Moore * PIL with preemption disabled. Therefore, this function must not be
193974072f41a843678abf5f61979c748687e66bSherry Moore * blocked.
193974072f41a843678abf5f61979c748687e66bSherry Moore *
193974072f41a843678abf5f61979c748687e66bSherry Moore * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
193974072f41a843678abf5f61979c748687e66bSherry Moore * DDI_FAILURE indicates an error condition and should almost never happen.
193974072f41a843678abf5f61979c748687e66bSherry Moore */
193974072f41a843678abf5f61979c748687e66bSherry Mooreint
193974072f41a843678abf5f61979c748687e66bSherry Mooreata_quiesce(dev_info_t *dip)
193974072f41a843678abf5f61979c748687e66bSherry Moore{
193974072f41a843678abf5f61979c748687e66bSherry Moore#ifdef ATA_DEBUG
193974072f41a843678abf5f61979c748687e66bSherry Moore /*
193974072f41a843678abf5f61979c748687e66bSherry Moore * Turn off debugging
193974072f41a843678abf5f61979c748687e66bSherry Moore */
193974072f41a843678abf5f61979c748687e66bSherry Moore ata_debug = 0;
193974072f41a843678abf5f61979c748687e66bSherry Moore#endif
193974072f41a843678abf5f61979c748687e66bSherry Moore
193974072f41a843678abf5f61979c748687e66bSherry Moore return (ata_devo_reset(dip, DDI_RESET_FORCE));
193974072f41a843678abf5f61979c748687e66bSherry Moore}
193974072f41a843678abf5f61979c748687e66bSherry Moore
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic struct cb_ops ata_cb_ops = {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_open, /* open */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nulldev, /* close */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nodev, /* strategy */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nodev, /* print */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nodev, /* dump */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_read, /* read */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nodev, /* write */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nodev, /* ioctl */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nodev, /* devmap */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nodev, /* mmap */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nodev, /* segmap */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nochpoll, /* chpoll */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_prop_op, /* prop_op */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf NULL, /* stream info */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf D_MP, /* driver compatibility flag */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf CB_REV, /* cb_ops revision */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nodev, /* aread */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nodev /* awrite */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf};
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic struct dev_ops ata_ops = {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf DEVO_REV, /* devo_rev, */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf 0, /* refcnt */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_getinfo_1to1, /* info */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf nulldev, /* identify */
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf NULL, /* probe */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_attach, /* attach */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_detach, /* detach */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_devo_reset, /* reset */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf &ata_cb_ops, /* driver operations */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf NULL, /* bus operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore ata_power, /* power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ata_quiesce /* quiesce */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf};
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* driver loadable module wrapper */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic struct modldrv modldrv = {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf &mod_driverops, /* Type of module. This one is a driver */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "ATA AT-bus attachment disk controller Driver", /* module name */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf &ata_ops, /* driver ops */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf};
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic struct modlinkage modlinkage = {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf MODREV_1, (void *)&modldrv, NULL
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf};
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#ifdef ATA_DEBUG
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ata_debug_init = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ata_debug_attach = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ata_debug = ADBG_FLAG_ERROR
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* | ADBG_FLAG_ARQ */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* | ADBG_FLAG_INIT */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* | ADBG_FLAG_TRACE */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* | ADBG_FLAG_TRANSPORT */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* | ADBG_FLAG_WARN */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#endif
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf_init(void)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int err;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#ifdef ATA_DEBUG
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_debug_init)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf debug_enter("\nATA _INIT\n");
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#endif
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((err = ddi_soft_state_init(&ata_state, sizeof (ata_ctl_t), 0)) != 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (err);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((err = scsi_hba_init(&modlinkage)) != 0) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_soft_state_fini(&ata_state);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (err);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* save pointer to SCSA provided bus_ops struct */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf scsa_bus_ops_p = ata_ops.devo_bus_ops;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* make a copy of SCSA bus_ops */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_bus_ops = *(ata_ops.devo_bus_ops);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Modify our bus_ops to call our routines. Our implementation
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * will determine if the device is ATA or ATAPI/SCSA and react
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * accordingly.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_bus_ops.bus_ctl = ata_bus_ctl;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* patch our bus_ops into the dev_ops struct */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ops.devo_bus_ops = &ata_bus_ops;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((err = mod_install(&modlinkage)) != 0) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf scsi_hba_fini(&modlinkage);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_soft_state_fini(&ata_state);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Initialize the per driver timer info.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_timer_init(&ata_timer_conf, drv_usectohz(ata_watchdog_usec));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (err);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf_fini(void)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int err;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((err = mod_remove(&modlinkage)) == 0) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_timer_fini(&ata_timer_conf);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf scsi_hba_fini(&modlinkage);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_soft_state_fini(&ata_state);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (err);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf_info(struct modinfo *modinfop)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (mod_info(&modlinkage, modinfop));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * driver attach entry point
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_attach(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *dip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_attach_cmd_t cmd)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *first_drvp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t targ;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t lun;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t lastlun;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int atapi_count = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int disk_count = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_attach entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#ifdef ATA_DEBUG
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_debug_attach)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf debug_enter("\nATA_ATTACH\n\n");
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#endif
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf switch (cmd) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case DDI_ATTACH:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf break;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case DDI_RESUME:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (ata_resume(dip));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf default:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* initialize controller */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp = ata_init_controller(dip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp == NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto errout;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&ata_ctlp->ac_ccc.ccc_hba_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* initialize drives */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (targ = 0; targ < ATA_MAXTARG; targ++) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp = ata_init_drive(ata_ctlp, targ, 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_drvp == NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (first_drvp == NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf first_drvp = ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ATAPIDRV(ata_drvp)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_count++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf lastlun = ata_drvp->ad_id.ai_lastlun;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf disk_count++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf lastlun = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * LUN support is currently disabled. Check with SFF-8070i
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * before enabling.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_enable_atapi_luns)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf lastlun = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Initialize higher LUNs, if there are any */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (lun = 1; lun <= lastlun && lun < ATA_MAXLUN; lun++) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((ata_drvp =
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_init_drive(ata_ctlp, targ, lun)) != NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_show_transfer_mode(ata_ctlp, ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((atapi_count == 0) && (disk_count == 0)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_attach: no drives detected\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto errout1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Always make certain that a valid drive is selected so
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * that routines which poll the status register don't get
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * confused by non-existent drives.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_drvhd,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf first_drvp->ad_drive_bits);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * make certain the drive selected
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_wait(ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf 0, ATS_BSY, 5000000)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ERROR(("ata_attach: select failed\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * initialize atapi/ata_dsk modules if we have at least
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * one drive of that type.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (atapi_count) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!atapi_attach(ata_ctlp))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto errout1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_flags |= AC_ATAPI_INIT;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (disk_count) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_disk_attach(ata_ctlp))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto errout1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_flags |= AC_DISK_INIT;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * make certain the interrupt and error latches are clear
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_pciide) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int instance = ddi_get_instance(dip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ddi_create_minor_node(dip, "control", S_IFCHR, instance,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf DDI_PSEUDO, 0) != DDI_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto errout1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_pciide_status_clear(ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * enable the interrupt handler and drop the mutex
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_flags |= AC_ATTACHED;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(&ata_ctlp->ac_ccc.ccc_hba_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_init_pm(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_report_dev(dip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_SUCCESS);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlferrout1:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(&ata_ctlp->ac_ccc.ccc_hba_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlferrout:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_detach(dip, DDI_DETACH);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* driver detach entry point */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_detach(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *dip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_detach_cmd_t cmd)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int instance;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int i;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int j;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_detach entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf switch (cmd) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case DDI_DETACH:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf break;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case DDI_SUSPEND:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (ata_suspend(dip));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf default:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf instance = ddi_get_instance(dip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp = ddi_get_soft_state(ata_state, instance);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_ctlp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_SUCCESS);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ata_ctlp->ac_pm_support) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATA_BUSY_COMPONENT(dip, 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ata_ctlp->ac_pm_level != PM_LEVEL_D0) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ATA_RAISE_POWER(dip, 0, PM_LEVEL_D0) !=
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf DDI_SUCCESS) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATA_IDLE_COMPONENT(dip, 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-components");
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_flags &= ~AC_ATTACHED;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* destroy ata module */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_flags & AC_DISK_INIT)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_disk_detach(ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* destroy atapi module */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_flags & AC_ATAPI_INIT)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_detach(ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_remove_minor_node(dip, NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* destroy drives */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (i = 0; i < ATA_MAXTARG; i++) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (j = 0; j < ATA_MAXLUN; j++) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp = CTL2DRV(ata_ctlp, i, j);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_drvp != NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_uninit_drive(ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_iohandle1)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_regs_map_free(&ata_ctlp->ac_iohandle1);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_iohandle2)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_regs_map_free(&ata_ctlp->ac_iohandle2);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_bmhandle)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_regs_map_free(&ata_ctlp->ac_bmhandle);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* destroy controller */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_destroy_controller(dip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf ddi_prop_remove_all(dip);
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_SUCCESS);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Nexus driver bus_ctl entry point
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*ARGSUSED*/
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_bus_ctl(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *d,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *r,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_ctl_enum_t o,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *a,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *v)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *tdip;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int target_type;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf char *bufp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_bus_ctl entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (o) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_SIDDEV:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_IOMIN:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Since we use PIO, we return a minimum I/O size of
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * one byte. This will need to be updated when we
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * implement DMA support
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *((int *)v) = 1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_SUCCESS);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_DMAPMAPC:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_REPORTINT:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_REGSIZE:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_NREGS:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_SLAVEONLY:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_AFFINITY:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_POKE:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_PEEK:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* These ops shouldn't be called by a target driver */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ERROR(("ata_bus_ctl: %s%d: invalid op (%d) from %s%d\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_driver_name(d), ddi_get_instance(d), o,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_driver_name(r), ddi_get_instance(r)));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_REPORTDEV:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_INITCHILD:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_CTLOPS_UNINITCHILD:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* these require special handling below */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf default:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ddi_ctlops(d, r, o, a, v));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* get targets dip */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (o == DDI_CTLOPS_INITCHILD || o == DDI_CTLOPS_UNINITCHILD)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf tdip = (dev_info_t *)a;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf tdip = r;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * XXX - Get class of target
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Before the "class" entry in a conf file becomes
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * a real property, we use an additional property
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * tentatively called "class_prop". We will require that
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * new classes (ie. direct) export "class_prop".
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * SCSA target drivers will not have this property, so
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * no property implies SCSA.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, tdip, DDI_PROP_DONTPASS,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "class", &bufp) == DDI_PROP_SUCCESS) ||
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (ddi_prop_lookup_string(DDI_DEV_T_ANY, tdip, DDI_PROP_DONTPASS,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "class_prop", &bufp) == DDI_PROP_SUCCESS)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (strcmp(bufp, "dada") == 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf target_type = ATA_DEV_DISK;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else if (strcmp(bufp, "scsi") == 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf target_type = ATA_DEV_ATAPI;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_bus_ctl: invalid target class %s\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf bufp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_prop_free(bufp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_prop_free(bufp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf target_type = ATA_DEV_ATAPI; /* no class prop, assume SCSI */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (o == DDI_CTLOPS_INITCHILD) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int instance = ddi_get_instance(d);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp = ddi_get_soft_state(ata_state, instance);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int targ;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int lun;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int drive_type;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf char *disk_prop;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf char *class_prop;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp == NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_bus_ctl: failed to find ctl struct\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* get (target,lun) of child device */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf targ = ddi_prop_get_int(DDI_DEV_T_ANY, tdip, DDI_PROP_DONTPASS,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "target", -1);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (targ == -1) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_bus_ctl: failed to get targ num\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf lun = ddi_prop_get_int(DDI_DEV_T_ANY, tdip, DDI_PROP_DONTPASS,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "lun", 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((targ < 0) || (targ >= ATA_MAXTARG) ||
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (lun < 0) || (lun >= ATA_MAXLUN)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp = CTL2DRV(ata_ctlp, targ, lun);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_drvp == NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE); /* no drive */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* get type of device */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ATAPIDRV(ata_drvp))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drive_type = ATA_DEV_ATAPI;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drive_type = ATA_DEV_DISK;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Check for special handling when child driver is
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * cmdk (which morphs to the correct interface)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (strcmp(ddi_get_name(tdip), "cmdk") == 0) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((target_type == ATA_DEV_DISK) &&
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (target_type != drive_type))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf target_type = drive_type;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (drive_type == ATA_DEV_ATAPI) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf class_prop = "scsi";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf disk_prop = "dadk";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf class_prop = "dada";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ndi_prop_update_string(DDI_DEV_T_NONE, tdip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "disk", disk_prop) != DDI_PROP_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_bus_ctl: failed to "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "create disk prop\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ndi_prop_update_string(DDI_DEV_T_NONE, tdip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "class_prop", class_prop) != DDI_PROP_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_bus_ctl: failed to "
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "create class prop\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Check that target class matches the device */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (target_type != drive_type)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (DDI_FAILURE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* save pointer to drive struct for ata_disk_bus_ctl */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_set_driver_private(tdip, ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Determine whether to enable DMA support for this drive. This
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * check is deferred to this point so that the various dma
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * properties could reside on the devinfo node should finer
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * grained dma control be required.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
5fb86bae323519d98a63f5829df4b849f1fe1598ml if (ata_drvp->ad_pciide_dma == ATA_DMA_UNINITIALIZED) {
5fb86bae323519d98a63f5829df4b849f1fe1598ml ata_drvp->ad_pciide_dma =
5fb86bae323519d98a63f5829df4b849f1fe1598ml ata_init_drive_pcidma(ata_ctlp, ata_drvp, tdip);
5fb86bae323519d98a63f5829df4b849f1fe1598ml ata_show_transfer_mode(ata_ctlp, ata_drvp);
5fb86bae323519d98a63f5829df4b849f1fe1598ml }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (target_type == ATA_DEV_ATAPI) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = scsa_bus_ops_p->bus_ctl(d, r, o, a, v);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ata_disk_bus_ctl(d, r, o, a, v);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * GHD ccc_hba_complete callback
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* ARGSUSED */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_hba_complete(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *hba_handle,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *gcmdp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int do_callback)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_hba_complete entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp = GCMD2DRV(gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp = GCMD2APKT(gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pktp->ap_complete)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (*ata_pktp->ap_complete)(ata_drvp, ata_pktp,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf do_callback);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* GHD ccc_timeout_func callback */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* ARGSUSED */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_timeout_func(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *hba_handle,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *gcmdp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gtgt_t *gtgtp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gact_t action,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int calltype)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp;
5fb86bae323519d98a63f5829df4b849f1fe1598ml ata_drv_t *ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_timeout_func entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp = (ata_ctl_t *)hba_handle;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (gcmdp != NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp = GCMD2APKT(gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (action) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case GACTION_EARLY_ABORT:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* abort before request was started */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pktp != NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_ABORT;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_complete(&ata_ctlp->ac_ccc, gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case GACTION_EARLY_TIMEOUT:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* timeout before request was started */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pktp != NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_TIMEOUT;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_complete(&ata_ctlp->ac_ccc, gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case GACTION_RESET_TARGET:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Reset a device is not supported. Resetting a specific
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * device can't be done at all to an ATA device and if
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * you send a RESET to an ATAPI device you have to
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * reset the whole bus to make certain both devices
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * on the bus stay in sync regarding which device is
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the currently selected one.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case GACTION_RESET_BUS:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Issue bus reset and reinitialize both drives.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * But only if this is a timed-out request. Target
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * driver reset requests are ignored because ATA
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * and ATAPI devices shouldn't be gratuitously reset.
5fb86bae323519d98a63f5829df4b849f1fe1598ml * Also disable DMA if it is a CF device.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (gcmdp == NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
5fb86bae323519d98a63f5829df4b849f1fe1598ml ata_drvp = GCMD2DRV(gcmdp);
5fb86bae323519d98a63f5829df4b849f1fe1598ml if (ata_drvp != NULL)
5fb86bae323519d98a63f5829df4b849f1fe1598ml if (ata_drvp->ad_id.ai_config == ATA_ID_CF_TO_ATA)
5fb86bae323519d98a63f5829df4b849f1fe1598ml ata_disable_DMA(ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ata_reset_bus(ata_ctlp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf default:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Initialize controller's soft-state structure
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic ata_ctl_t *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_init_controller(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *dip)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int instance;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t ioaddr1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t ioaddr2;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_init_controller entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf instance = ddi_get_instance(dip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* allocate controller structure */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ddi_soft_state_zalloc(ata_state, instance) != DDI_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_init_controller: soft_state_zalloc failed\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp = ddi_get_soft_state(ata_state, instance);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp == NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_init_controller: failed to find "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "controller struct\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * initialize per-controller data
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_dip = dip;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_arq_pktp = kmem_zalloc(sizeof (ata_pkt_t), KM_SLEEP);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * map the device registers
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_setup_ioaddr(dip, &ata_ctlp->ac_iohandle1, &ioaddr1,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf &ata_ctlp->ac_iohandle2, &ioaddr2,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf &ata_ctlp->ac_bmhandle, &ata_ctlp->ac_bmaddr)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_detach(dip, DDI_DETACH);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_INIT(("ata_init_controller: ioaddr1 = 0x%p, ioaddr2 = 0x%p\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ioaddr1, ioaddr2));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Do ARQ setup
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_init_arq(ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Do PCI-IDE setup
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_init_pciide(dip, ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * port addresses associated with ioaddr1
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_ioaddr1 = ioaddr1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_data = (ushort_t *)ioaddr1 + AT_DATA;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_error = (uchar_t *)ioaddr1 + AT_ERROR;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_feature = (uchar_t *)ioaddr1 + AT_FEATURE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_count = (uchar_t *)ioaddr1 + AT_COUNT;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_sect = (uchar_t *)ioaddr1 + AT_SECT;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_lcyl = (uchar_t *)ioaddr1 + AT_LCYL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_hcyl = (uchar_t *)ioaddr1 + AT_HCYL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_drvhd = (uchar_t *)ioaddr1 + AT_DRVHD;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_status = (uchar_t *)ioaddr1 + AT_STATUS;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_cmd = (uchar_t *)ioaddr1 + AT_CMD;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * port addresses associated with ioaddr2
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_ioaddr2 = ioaddr2;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_altstatus = (uchar_t *)ioaddr2 + AT_ALTSTATUS;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_devctl = (uchar_t *)ioaddr2 + AT_DEVCTL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If AC_BSY_WAIT needs to be set for laptops that do
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * suspend/resume but do not correctly wait for the busy bit to
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * drop after a resume.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_timing_flags = ddi_prop_get_int(DDI_DEV_T_ANY,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf dip, DDI_PROP_DONTPASS, "timing_flags", 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * get max transfer size, default to 256 sectors
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_max_transfer = ddi_prop_get_int(DDI_DEV_T_ANY,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf dip, DDI_PROP_DONTPASS, "max_transfer", 0x100);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_max_transfer < 1)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_max_transfer = 1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_max_transfer > 0x100)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_max_transfer = 0x100;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Get the standby timer value
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_standby_time = ddi_prop_get_int(DDI_DEV_T_ANY,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf dip, DDI_PROP_DONTPASS, "standby", -1);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If this is a /pci/pci-ide instance check to see if
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * it's supposed to be attached as an /isa/ata
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_pciide) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf static char prop_buf[] = "SUNW-ata-ffff-isa";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int addr1 = (intptr_t)ioaddr1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (addr1 < 0 || addr1 > 0xffff) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_detach(dip, DDI_DETACH);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) sprintf(prop_buf, "SUNW-ata-%04x-isa",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf addr1);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_root_node(),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf DDI_PROP_DONTPASS, prop_buf)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_detach(dip, DDI_DETACH);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Init controller specific stuff */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_spec_init_controller(dip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * initialize GHD
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GHD_WAITQ_INIT(&ata_ctlp->ac_ccc.ccc_waitq, NULL, 1);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ghd_register("ata", &ata_ctlp->ac_ccc, dip, 0, ata_ctlp,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf atapi_ccballoc, atapi_ccbfree,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_pciide_dma_sg_func, ata_hba_start,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_hba_complete, ata_intr,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_get_status, ata_process_intr, ata_timeout_func,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf &ata_timer_conf, NULL)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_detach(dip, DDI_DETACH);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_flags |= AC_GHD_INIT;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* destroy a controller */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_destroy_controller(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *dip)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int instance;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_destroy_controller entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf instance = ddi_get_instance(dip);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp = ddi_get_soft_state(ata_state, instance);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp == NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* destroy ghd */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_flags & AC_GHD_INIT)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_unregister(&ata_ctlp->ac_ccc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* free the pciide buffer (if any) */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pciide_free(ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* destroy controller struct */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf kmem_free(ata_ctlp->ac_arq_pktp, sizeof (ata_pkt_t));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_soft_state_free(ata_state, instance);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * initialize a drive
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic ata_drv_t *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_init_drive(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t targ,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t lun)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf static char nec_260[] = "NEC CD-ROM DRIVE";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf struct ata_id *aidp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf char buf[80];
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int drive_type;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int i;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int valid_version = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_init_drive entered, targ = %d, lun = %d\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf targ, lun));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* check if device already exists */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp = CTL2DRV(ata_ctlp, targ, lun);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_drvp != NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* allocate new device structure */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp = kmem_zalloc(sizeof (ata_drv_t), KM_SLEEP);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf aidp = &ata_drvp->ad_id;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * set up drive struct
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_ctlp = ata_ctlp;
5fb86bae323519d98a63f5829df4b849f1fe1598ml ata_drvp->ad_pciide_dma = ATA_DMA_UNINITIALIZED;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_targ = targ;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_drive_bits =
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ata_drvp->ad_targ == 0 ? ATDH_DRIVE0 : ATDH_DRIVE1);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Add the LUN for SFF-8070i support
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_lun = lun;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_drive_bits |= ata_drvp->ad_lun;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * get drive type, side effect is to collect
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * IDENTIFY DRIVE data
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drive_type = ata_drive_type(ata_drvp->ad_drive_bits,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_iohandle1,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_ioaddr1,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_iohandle2,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_ioaddr2,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (drive_type) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_DEV_NONE:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* no drive found */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto errout;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_DEV_ATAPI:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_flags |= AD_ATAPI;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_DEV_DISK:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_flags |= AD_DISK;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * swap bytes of all text fields
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_strncmp(nec_260, aidp->ai_model, sizeof (aidp->ai_model))) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf swab(aidp->ai_drvser, aidp->ai_drvser,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf sizeof (aidp->ai_drvser));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf swab(aidp->ai_fw, aidp->ai_fw,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf sizeof (aidp->ai_fw));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf swab(aidp->ai_model, aidp->ai_model,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf sizeof (aidp->ai_model));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Check if this drive has the Single Sector bug
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_check_drive_blacklist(&ata_drvp->ad_id, ATA_BL_1SECTOR))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_flags |= AD_1SECTOR;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_flags &= ~AD_1SECTOR;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
8c112d45d87338e20826001e18cb9e22e5187658Colin Yi if (ata_check_drive_blacklist(&ata_drvp->ad_id, ATA_BL_LBA48))
8c112d45d87338e20826001e18cb9e22e5187658Colin Yi ata_drvp->ad_flags |= AD_BLLBA48;
8c112d45d87338e20826001e18cb9e22e5187658Colin Yi else
8c112d45d87338e20826001e18cb9e22e5187658Colin Yi ata_drvp->ad_flags &= ~AD_BLLBA48;
8c112d45d87338e20826001e18cb9e22e5187658Colin Yi
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Check if this drive has the "revert to defaults" bug */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_check_revert_to_defaults(ata_drvp))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_flags |= AD_NORVRT;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Dump the drive info */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) strncpy(buf, aidp->ai_model, sizeof (aidp->ai_model));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf buf[sizeof (aidp->ai_model)-1] = '\0';
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (i = sizeof (aidp->ai_model) - 2; buf[i] == ' '; i--)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf buf[i] = '\0';
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\t%s device at targ %d, lun %d lastlun 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ATAPIDRV(ata_drvp) ? "ATAPI":"IDE"),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_drvp->ad_targ, ata_drvp->ad_lun, aidp->ai_lastlun));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\tmodel %s\n", buf));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (aidp->ai_majorversion != 0 && aidp->ai_majorversion != 0xffff) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (i = 14; i >= 2; i--) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (aidp->ai_majorversion & (1 << i)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf valid_version = i;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT((
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "?\tATA/ATAPI-%d supported, majver 0x%x minver 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf valid_version,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_majorversion,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_minorversion));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_capability_data) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\t\tstat %x, err %x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_get8(ata_ctlp->ac_iohandle2,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_altstatus),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_get8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_error)));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\t\tcfg 0x%x, cap 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_config,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_cap));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Be aware that ATA-6 and later drives may not provide valid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * geometry information and other obsoleted info.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Select what is printed based on supported ATA model (skip
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * anything below ATA/ATAPI-3)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (valid_version == 0 || aidp->ai_majorversion <
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAC_MAJVER_6) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Supported version less then ATA-6
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\t\tcyl %d, hd %d, sec/trk %d\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_fixcyls,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_heads,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_sectors));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\t\tmult1 0x%x, mult2 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_mult1,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_mult2));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (valid_version && aidp->ai_majorversion < ATAC_MAJVER_4) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT((
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "?\t\tpiomode 0x%x, dmamode 0x%x, advpiomode 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_piomode,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_dmamode,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_advpiomode));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\t\tadvpiomode 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_advpiomode));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\t\tminpio %d, minpioflow %d\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_minpio,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_minpioflow));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (valid_version && aidp->ai_majorversion >= ATAC_MAJVER_4 &&
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (aidp->ai_validinfo & ATAC_VALIDINFO_83)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\t\tdwdma 0x%x, ultradma 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_dworddma,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_ultradma));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\t\tdwdma 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf aidp->ai_dworddma));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ATAPIDRV(ata_drvp)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!atapi_init_drive(ata_drvp))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto errout;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_disk_init_drive(ata_drvp))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto errout;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * store pointer in controller struct
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf CTL2DRV(ata_ctlp, targ, lun) = ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * lock the drive's current settings in case I have to
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * reset the drive due to some sort of error
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) ata_set_feature(ata_ctlp, ata_drvp, ATSF_DIS_REVPOD, 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlferrout:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_uninit_drive(ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* destroy a drive */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_uninit_drive(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#if 0
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#endif
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_uninit_drive entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#if 0
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * DON'T DO THIS. disabling interrupts floats the IRQ line
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * which generates spurious interrupts
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Select the correct drive
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_drvhd,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_drvp->ad_drive_bits);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Disable interrupts from the drive
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(ata_ctlp->ac_iohandle2, ata_ctlp->ac_devctl,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ATDC_D3 | ATDC_NIEN));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#endif
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* interface specific clean-ups */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_drvp->ad_flags & AD_ATAPI)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_uninit_drive(ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else if (ata_drvp->ad_flags & AD_DISK)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_disk_uninit_drive(ata_drvp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* free drive struct */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf kmem_free(ata_drvp, sizeof (ata_drv_t));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ata_drive_type()
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The timeout values and exact sequence of checking is critical
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * especially for atapi device detection, and should not be changed lightly.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_drive_type(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t drvhd,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl1,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t ioaddr1,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl2,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t ioaddr2,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf struct ata_id *ata_id_bufp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t status;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_drive_type entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * select the appropriate drive and LUN
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, (uchar_t *)ioaddr1 + AT_DRVHD, drvhd);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * make certain the drive is selected, and wait for not busy
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_wait3(io_hdl2, ioaddr2, 0, ATS_BSY, 0x7f, 0, 0x7f, 0,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf 5 * 1000000);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf status = ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf if (status & ATS_BSY) {
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ADBG_TRACE(("ata_drive_type 0x%p 0x%x\n", ioaddr1, status));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DEV_NONE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_disk_id(io_hdl1, ioaddr1, io_hdl2, ioaddr2, ata_id_bufp))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DEV_DISK);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * No disk, check for atapi unit.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!atapi_signature(io_hdl1, ioaddr1)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#ifndef ATA_DISABLE_ATAPI_1_7
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Check for old (but prevalent) atapi 1.7B
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * spec device, the only known example is the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * NEC CDR-260 (not 260R which is (mostly) ATAPI 1.2
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * compliant). This device has no signature
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * and requires conversion from hex to BCD
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * for some scsi audio commands.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (atapi_id(io_hdl1, ioaddr1, io_hdl2, ioaddr2, ata_id_bufp)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DEV_ATAPI);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#endif
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DEV_NONE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (atapi_id(io_hdl1, ioaddr1, io_hdl2, ioaddr2, ata_id_bufp)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DEV_ATAPI);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DEV_NONE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
9f49ae270d37efd5c5270cb8046b4229b5380021mlf/*
9f49ae270d37efd5c5270cb8046b4229b5380021mlf * nsec-granularity time delay function
9f49ae270d37efd5c5270cb8046b4229b5380021mlf */
9f49ae270d37efd5c5270cb8046b4229b5380021mlfvoid
9f49ae270d37efd5c5270cb8046b4229b5380021mlfata_nsecwait(clock_t count)
9f49ae270d37efd5c5270cb8046b4229b5380021mlf{
9f49ae270d37efd5c5270cb8046b4229b5380021mlf extern int tsc_gethrtime_initted;
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
9f49ae270d37efd5c5270cb8046b4229b5380021mlf if (tsc_gethrtime_initted) {
9f49ae270d37efd5c5270cb8046b4229b5380021mlf hrtime_t end = gethrtime() + count;
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
9f49ae270d37efd5c5270cb8046b4229b5380021mlf while (gethrtime() < end) {
9f49ae270d37efd5c5270cb8046b4229b5380021mlf SMT_PAUSE();
9f49ae270d37efd5c5270cb8046b4229b5380021mlf }
9f49ae270d37efd5c5270cb8046b4229b5380021mlf } else {
9f49ae270d37efd5c5270cb8046b4229b5380021mlf drv_usecwait(1 + (count / 1000));
9f49ae270d37efd5c5270cb8046b4229b5380021mlf }
9f49ae270d37efd5c5270cb8046b4229b5380021mlf}
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Wait for a register of a controller to achieve a specific state.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * To return normally, all the bits in the first sub-mask must be ON,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * all the bits in the second sub-mask must be OFF.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If timeout_usec microseconds pass without the controller achieving
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the desired bit configuration, we return TRUE, else FALSE.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ata_usec_delay = 10;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_wait(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t ioaddr,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t onbits,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t offbits,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t timeout_usec)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ushort_t val;
9f49ae270d37efd5c5270cb8046b4229b5380021mlf hrtime_t deadline = gethrtime() +
9f49ae270d37efd5c5270cb8046b4229b5380021mlf (hrtime_t)timeout_usec * (NANOSEC / MICROSEC);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf do {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf val = ddi_get8(io_hdl, (uchar_t *)ioaddr + AT_ALTSTATUS);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((val & onbits) == onbits && (val & offbits) == 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drv_usecwait(ata_usec_delay);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf } while (gethrtime() < deadline);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * This is a slightly more complicated version that checks
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * for error conditions and bails-out rather than looping
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * until the timeout expires
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_wait3(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t ioaddr,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t onbits1,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t offbits1,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t failure_onbits2,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t failure_offbits2,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t failure_onbits3,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t failure_offbits3,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t timeout_usec)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ushort_t val;
9f49ae270d37efd5c5270cb8046b4229b5380021mlf hrtime_t deadline = gethrtime() +
9f49ae270d37efd5c5270cb8046b4229b5380021mlf (hrtime_t)timeout_usec * (NANOSEC / MICROSEC);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf do {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf val = ddi_get8(io_hdl, (uchar_t *)ioaddr + AT_ALTSTATUS);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * check for expected condition
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((val & onbits1) == onbits1 && (val & offbits1) == 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * check for error conditions
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((val & failure_onbits2) == failure_onbits2 &&
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (val & failure_offbits2) == 0) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((val & failure_onbits3) == failure_onbits3 &&
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (val & failure_offbits3) == 0) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drv_usecwait(ata_usec_delay);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf } while (gethrtime() < deadline);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * low level routine for ata_disk_id() and atapi_id()
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_id_common(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t id_cmd,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int expect_drdy,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl1,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t ioaddr1,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl2,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t ioaddr2,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf struct ata_id *aidp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t status;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_id_common entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf bzero(aidp, sizeof (struct ata_id));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * clear the features register
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, (uchar_t *)ioaddr1 + AT_FEATURE, 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf * Disable interrupts from the device. When the ata
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf * hardware is sharing its interrupt with another
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf * device, the shared interrupt might have already been
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf * unmasked in the interrupt controller and
9f49ae270d37efd5c5270cb8046b4229b5380021mlf * triggering ata device interrupts will result in an
9f49ae270d37efd5c5270cb8046b4229b5380021mlf * interrupt storm and a hung system.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ddi_put8(io_hdl2, (uchar_t *)ioaddr2 + AT_DEVCTL, ATDC_D3 | ATDC_NIEN);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * issue IDENTIFY DEVICE or IDENTIFY PACKET DEVICE command
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, (uchar_t *)ioaddr1 + AT_CMD, id_cmd);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* wait for the busy bit to settle */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf /*
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf * read alternate status and check for conditions which
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf * may indicate the drive is not present, to prevent getting
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf * stuck in ata_wait3() below.
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf */
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf status = ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS);
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf /*
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf * 0x0, 0x7f, or ATS_DF can happen when no drive is present
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf */
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf if ((status == 0x0) || (status == 0x7f) ||
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf ((status & (ATS_BSY|ATS_DF)) == ATS_DF)) {
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf /* invalid status, can't be an ATA or ATAPI device */
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf return (FALSE);
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf }
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * According to the ATA specification, some drives may have
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * to read the media to complete this command. We need to
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * make sure we give them enough time to respond.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_wait3(io_hdl2, ioaddr2, 0, ATS_BSY,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATS_ERR, ATS_BSY, 0x7f, 0, 5 * 1000000);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * read the status byte and clear the pending interrupt
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf status = ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_STATUS);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf * this happens if there's no drive present
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
b3c0e203b148ecc85043c9da9d327d45c6e7c470mlf if (status == 0xff || status == 0x7f) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* invalid status, can't be an ATA or ATAPI device */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (status & ATS_BSY) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ERROR(("ata_id_common: BUSY status 0x%x error 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_get8(io_hdl2, (uchar_t *)ioaddr2 +AT_ALTSTATUS),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR)));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!(status & ATS_DRQ)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (status & (ATS_ERR | ATS_DF)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Give the drive another second to assert DRQ. Some older
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic * drives de-assert BSY before asserting DRQ. Bail out
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic * immediately if the status becomes 0x7f, which is invalid
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic * value. It can happen when no drive is present.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic if (!ata_wait3(io_hdl2, ioaddr2, ATS_DRQ, ATS_BSY, 0x7f,
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic ATS_BSY, 0x7f, ATS_BSY, 1000000)) {
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic ADBG_WARN(("ata_id_common: "
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic "!DRQ status 0x%x error 0x%x\n",
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic ddi_get8(io_hdl2, (uchar_t *)ioaddr2 +AT_ALTSTATUS),
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR)));
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * transfer the data
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_rep_get16(io_hdl1, (ushort_t *)aidp, (ushort_t *)ioaddr1 + AT_DATA,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf NBPSCTR >> 1, DDI_DEV_NO_AUTOINCR);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* wait for the busy bit to settle */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Wait for the drive to recognize I've read all the data.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Some drives have been observed to take as much as 3msec to
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic * deassert DRQ after reading the data; allow 1 sec just in case.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Note: some non-compliant ATAPI drives (e.g., NEC Multispin 6V,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * CDR-1350A) don't assert DRDY. If we've made it this far we can
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * safely ignore the DRDY bit since the ATAPI Packet command
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * actually doesn't require it to ever be asserted.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic * Bail out immediately if the status becomes 0x7f, which is invalid
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic * value. It can happen when no drive is present.
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic if (!ata_wait3(io_hdl2, ioaddr2, (uchar_t)(expect_drdy ? ATS_DRDY : 0),
ab5a7454a6d76e82a121d74c74d5589cc3d37a8fvitezslav batrla - Sun Microsystems - Prague Czech Republic (ATS_BSY | ATS_DRQ), 0x7f, ATS_BSY, 0x7f, ATS_BSY, 1000000)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_id_common: bad status 0x%x error 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR)));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Check to see if the command aborted. This happens if
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * an IDENTIFY DEVICE command is issued to an ATAPI PACKET device,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * or if an IDENTIFY PACKET DEVICE command is issued to an ATA
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * (non-PACKET) device.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (status & (ATS_DF | ATS_ERR)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_id_common: status 0x%x error 0x%x \n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR)));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Low level routine to issue a non-data command and busy wait for
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the completion status.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_command(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int expect_drdy,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int silent,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t busy_wait,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t cmd,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t feature,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t count,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t sector,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t head,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t cyl_low,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t cyl_hi)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t status;
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 /* make certain the drive selected */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (uchar_t)(expect_drdy ? ATS_DRDY : 0),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATS_BSY, busy_wait)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ERROR(("ata_command: select failed "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "DRDY 0x%x CMD 0x%x F 0x%x N 0x%x "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "S 0x%x H 0x%x CL 0x%x CH 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf expect_drdy, cmd, feature, count,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf sector, head, cyl_low, cyl_hi));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * set all the regs
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, (head | ata_drvp->ad_drive_bits));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_sect, sector);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_count, count);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_lcyl, cyl_low);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_hcyl, cyl_hi);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_feature, feature);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* send the command */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_cmd, cmd);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* wait for the busy bit to settle */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf ata_nsecwait(400);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* wait for not busy */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2, 0, ATS_BSY, busy_wait)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ERROR(("ata_command: BSY too long!"
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "DRDY 0x%x CMD 0x%x F 0x%x N 0x%x "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "S 0x%x H 0x%x CL 0x%x CH 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf expect_drdy, cmd, feature, count,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf sector, head, cyl_low, cyl_hi));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * wait for DRDY before continuing
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_wait3(io_hdl2, ata_ctlp->ac_ioaddr2,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATS_DRDY, ATS_BSY, /* okay */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATS_ERR, ATS_BSY, /* cmd failed */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATS_DF, ATS_BSY, /* drive failed */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf busy_wait);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* read status to clear IRQ, and check for error */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf status = ddi_get8(io_hdl1, ata_ctlp->ac_status);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((status & (ATS_BSY | ATS_DF | ATS_ERR)) == 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!silent) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ERROR(("ata_command status 0x%x error 0x%x "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "DRDY 0x%x CMD 0x%x F 0x%x N 0x%x "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "S 0x%x H 0x%x CL 0x%x CH 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_get8(io_hdl1, ata_ctlp->ac_status),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_get8(io_hdl1, ata_ctlp->ac_error),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf expect_drdy, cmd, feature, count,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf sector, head, cyl_low, cyl_hi));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Issue a SET FEATURES command
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_set_feature(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t feature,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t value)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ata_command(ata_ctlp, ata_drvp, TRUE, TRUE, ata_set_feature_wait,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATC_SET_FEAT, feature, value, 0, 0, 0, 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* feature, count, sector, head, cyl_low, cyl_hi */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ERROR(("?ata_set_feature: (0x%x,0x%x) failed\n", feature, value));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Issue a FLUSH CACHE command
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_flush_cache(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* this command is optional so fail silently */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ata_command(ata_ctlp, ata_drvp, TRUE, TRUE,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_flush_cache_wait,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATC_FLUSH_CACHE, 0, 0, 0, 0, 0, 0));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ata_setup_ioaddr()
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Map the device registers and return the handles.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If this is a ISA-ATA controller then only two handles are
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * initialized and returned.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If this is a PCI-IDE controller than a third handle (for the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * PCI-IDE Bus Mastering registers) is initialized and returned.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_setup_ioaddr(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *dip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t *handle1p,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t *addr1p,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t *handle2p,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t *addr2p,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t *bm_hdlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t *bm_addrp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_device_acc_attr_t dev_attr;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rnumber;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf off_t regsize;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Make certain the controller is enabled and its regs are map-able
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ddi_dev_regsize(dip, 0, &regsize);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc != DDI_SUCCESS || regsize <= AT_CMD) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_INIT(("ata_setup_ioaddr(1): rc %d regsize %lld\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf rc, (long long)regsize));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ddi_dev_regsize(dip, 1, &regsize);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc != DDI_SUCCESS || regsize <= AT_ALTSTATUS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_INIT(("ata_setup_ioaddr(2): rc %d regsize %lld\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf rc, (long long)regsize));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * setup the device attribute structure for little-endian,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * strict ordering access.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *handle1p = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *handle2p = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *bm_hdlp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Determine whether this is a ISA, PNP-ISA, or PCI-IDE device
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "pnp-csn")) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* it's PNP-ISA, skip over the extra reg tuple */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnumber = 1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto not_pciide;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* else, it's ISA or PCI-IDE, check further */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnumber = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!ata_is_pci(dip)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If it's not a PCI-IDE, there are only two reg tuples
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * and the first one contains the I/O base (170 or 1f0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * rather than the controller instance number.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_setup_ioaddr !pci-ide\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto not_pciide;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Map the correct half of the PCI-IDE Bus Master registers.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * There's a single BAR that maps these registers for both
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * controller's in a dual-controller chip and it's upto my
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * parent nexus, pciide, to adjust which (based on my instance
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * number) half this call maps.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ddi_dev_regsize(dip, 2, &regsize);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc != DDI_SUCCESS || regsize < 8) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_INIT(("ata_setup_ioaddr(3): rc %d regsize %lld\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf rc, (long long)regsize));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto not_pciide;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ddi_regs_map_setup(dip, 2, bm_addrp, 0, 0, &dev_attr, bm_hdlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc != DDI_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* map failed, try to use in non-pci-ide mode */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_setup_ioaddr bus master map failed, rc=0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf rc));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *bm_hdlp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfnot_pciide:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * map the lower command block registers
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ddi_regs_map_setup(dip, rnumber, addr1p, 0, 0, &dev_attr,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf handle1p);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc != DDI_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cmn_err(CE_WARN, "ata: reg tuple 0 map failed, rc=0x%x\n", rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto out1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If the controller is being used in compatibility mode
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * via /devices/isa/ata@1,{1f0,1f0}/..., the reg property
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * will specify zeros for the I/O ports for the PCI
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * instance.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (*addr1p == 0) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_setup_ioaddr ioaddr1 0\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto out2;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * map the upper control block registers
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ddi_regs_map_setup(dip, rnumber + 1, addr2p, 0, 0, &dev_attr,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf handle2p);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc == DDI_SUCCESS)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cmn_err(CE_WARN, "ata: reg tuple 1 map failed, rc=0x%x", rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfout2:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (*handle1p != NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_regs_map_free(handle1p);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *handle1p = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfout1:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (*bm_hdlp != NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_regs_map_free(bm_hdlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *bm_hdlp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Currently, the only supported controllers are ones which
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * support the SFF-8038 Bus Mastering spec.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Check the parent node's IEEE 1275 class-code property to
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * determine if it's an PCI-IDE instance which supports SFF-8038
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Bus Mastering. It's perfectly valid to have a PCI-IDE controller
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * that doesn't do Bus Mastering. In that case, my interrupt handler
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * only uses the interrupt latch bit in PCI-IDE status register.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The assumption is that the programming interface byte of the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * class-code property reflects the bus master DMA capability of
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the controller.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Whether the drive support supports the DMA option still needs
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * to be checked later. Each individual request also has to be
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * checked for alignment and size to decide whether to use the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * DMA transfer mode.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_init_pciide(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *dip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t class_code;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t status;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_cntrl_DMA_sel_msg = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_bmhandle == NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_pciide = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_pciide_bm = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_cntrl_DMA_sel_msg = "cntrl not Bus Master DMA capable";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * check if it's a known bogus PCI-IDE chip
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_check_pciide_blacklist(dip, ATA_BL_BOGUS)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_setup_ioaddr pci-ide blacklist\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_pciide = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_pciide_bm = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_cntrl_DMA_sel_msg = "cntrl blacklisted";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_pciide = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_check_pciide_blacklist(dip, ATA_BL_BMSTATREG_PIO_BROKEN)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_flags |= AC_BMSTATREG_PIO_BROKEN;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * check for a PCI-IDE chip with a broken DMA engine
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_check_pciide_blacklist(dip, ATA_BL_NODMA)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_pciide_bm = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_cntrl_DMA_sel_msg =
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "cntrl blacklisted/DMA engine broken";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Check the Programming Interface register to determine
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * if this device supports PCI-IDE Bus Mastering. Some PCI-IDE
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * devices don't support Bus Mastering or DMA.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Since we are dealing with pre-qualified pci-ide controller,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * check programming interface byte only.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf class_code = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf DDI_PROP_DONTPASS, "class-code", 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((class_code & PCIIDE_BM_CAP_MASK) != PCIIDE_BM_CAP_MASK) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_pciide_bm = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_cntrl_DMA_sel_msg =
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "cntrl not Bus Master DMA capable";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Avoid doing DMA on "simplex" chips which share hardware
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * between channels
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf status = ddi_get8(ata_ctlp->ac_bmhandle,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (uchar_t *)ata_ctlp->ac_bmaddr + PCIIDE_BMISX_REG);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Some motherboards have CSB5's that are wired "to emulate CSB4 mode".
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * In such a mode, the simplex bit is asserted, but in fact testing
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * on such a motherboard has shown that the devices are not simplex
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * -- DMA can be used on both channels concurrently with no special
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * considerations. For chips like this, we have the ATA_BL_NO_SIMPLEX
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * flag set to indicate that the value of the simplex bit can be
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ignored.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (status & PCIIDE_BMISX_SIMPLEX) {
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf if (ata_check_pciide_blacklist(dip, ATA_BL_NO_SIMPLEX)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cmn_err(CE_WARN, "Ignoring false simplex bit \n");
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf int simplex_dma_channel, *rp, proplen, channel;
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf int dma_on = FALSE;
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf /*
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf * By default,use DMA on channel 0 and PIO on channel
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf * 1. This can be switched by setting
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf * ata-simplex-dma-channel to:
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf * 0 DMA on channel 0 (default without this
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf * property)
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf * 1 DMA on channel 1
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf * any other value: DMA off on both channels.
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf */
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf simplex_dma_channel = ata_prop_lookup_int(DDI_DEV_T_ANY,
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf ata_ctlp->ac_dip, 0, "ata-simplex-dma-channel", 0);
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf ata_ctlp->ac_dip, DDI_PROP_DONTPASS, "reg", &rp,
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf (uint_t *)&proplen) == DDI_PROP_SUCCESS) {
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf channel = *rp;
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf ddi_prop_free(rp);
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf if (simplex_dma_channel == channel) {
ab4f33c9d90dd2fe40a830e0db03f337b4b65b21ml cmn_err(CE_CONT, "?ata: simplex "
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf "controller. DMA on channel"
ab4f33c9d90dd2fe40a830e0db03f337b4b65b21ml " %d PIO on channel %d",
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf channel, channel ? 0:1);
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf dma_on = TRUE;
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf } else {
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf ata_cntrl_DMA_sel_msg =
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf "simplex controller";
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf }
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf }
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf if (dma_on == FALSE) {
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf ata_ctlp->ac_pciide_bm = FALSE;
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf return;
d39757aa11b7b514615ceb1ec0388a6d0521a202mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * It's a compatible PCI-IDE Bus Mastering controller,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * allocate and map the DMA Scatter/Gather list (PRDE table).
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pciide_alloc(dip, ata_ctlp))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_pciide_bm = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_pciide_bm = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_cntrl_DMA_sel_msg = "unable to init DMA S/G list";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Determine whether to enable DMA support for this drive.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The controller and the drive both have to support DMA.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The controller's capabilities were already checked in
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ata_init_pciide(), now just check the drive's capabilities.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_init_drive_pcidma(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *tdip)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf boolean_t dma;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf boolean_t cd_dma;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf boolean_t disk_dma;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf boolean_t atapi_dma;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int ata_options;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_dev_DMA_sel_msg = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_pciide_bm != TRUE) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_dev_DMA_sel_msg =
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "controller is not Bus Master capable";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DMA_OFF);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_options = ddi_prop_get_int(DDI_DEV_T_ANY, ata_ctlp->ac_dip,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf 0, "ata-options", 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!(ata_options & ATA_OPTIONS_DMA)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Either the ata-options property was not found or
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * DMA is not enabled by this property
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_dev_DMA_sel_msg =
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "disabled by \"ata-options\" property";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DMA_OFF);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_check_drive_blacklist(&ata_drvp->ad_id, ATA_BL_NODMA)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_dev_DMA_sel_msg = "device not DMA capable; blacklisted";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DMA_OFF);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * DMA mode is mandatory on ATA-3 (or newer) drives but is
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * optional on ATA-2 (or older) drives.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * On ATA-2 drives the ai_majorversion word will probably
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * be 0xffff or 0x0000, check the (now obsolete) DMA bit in
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the capabilities word instead. The order of these tests
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * is important since an ATA-3 drive doesn't have to set
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the DMA bit in the capabilities word.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!((ata_drvp->ad_id.ai_majorversion & 0x8000) == 0 &&
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_id.ai_majorversion >= (1 << 2)) &&
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf !(ata_drvp->ad_id.ai_cap & ATAC_DMA_SUPPORT)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_dev_DMA_sel_msg = "device not DMA capable";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DMA_OFF);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China /*
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China * Disable DMA for ATAPI devices on controllers known to
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China * have trouble with ATAPI DMA
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China */
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China if (ATAPIDRV(ata_drvp)) {
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China if (ata_check_pciide_blacklist(ata_ctlp->ac_dip,
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China ATA_BL_ATAPI_NODMA)) {
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China ata_dev_DMA_sel_msg =
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China "controller incapable of DMA for ATAPI device";
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China return (ATA_DMA_OFF);
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China }
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dma = ata_prop_lookup_int(DDI_DEV_T_ANY, tdip,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf 0, "ata-dma-enabled", TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf disk_dma = ata_prop_lookup_int(DDI_DEV_T_ANY, tdip,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf 0, "ata-disk-dma-enabled", TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cd_dma = ata_prop_lookup_int(DDI_DEV_T_ANY, tdip,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf 0, "atapi-cd-dma-enabled", FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_dma = ata_prop_lookup_int(DDI_DEV_T_ANY, tdip,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf 0, "atapi-other-dma-enabled", TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (dma == FALSE) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cmn_err(CE_CONT, "?ata_init_drive_pcidma: "
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "DMA disabled by \"ata-dma-enabled\" property");
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_dev_DMA_sel_msg = "disabled by prop ata-dma-enabled";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DMA_OFF);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (IS_CDROM(ata_drvp) == TRUE) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (cd_dma == FALSE) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_dev_DMA_sel_msg =
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "disabled. Control with \"atapi-cd-dma-enabled\""
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf " property";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DMA_OFF);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else if (ATAPIDRV(ata_drvp) == FALSE) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (disk_dma == FALSE) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_dev_DMA_sel_msg =
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "disabled by \"ata-disk-dma-enabled\" property";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DMA_OFF);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else if (atapi_dma == FALSE) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_dev_DMA_sel_msg =
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "disabled by \"atapi-other-dma-enabled\" property";
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DMA_OFF);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_DMA_ON);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * this compare routine squeezes out extra blanks and
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * returns TRUE if p1 matches the leftmost substring of p2
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_strncmp(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf char *p1,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf char *p2,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int cnt)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (;;) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * skip over any extra blanks in both strings
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf while (*p1 != '\0' && *p1 == ' ')
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf p1++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf while (cnt != 0 && *p2 == ' ') {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf p2++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cnt--;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * compare the two strings
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (cnt == 0 || *p1 != *p2)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf while (cnt > 0 && *p1 == *p2) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf p1++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf p2++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cnt--;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* return TRUE if both strings ended at same point */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return ((*p1 == '\0') ? TRUE : FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Per PSARC/1997/281 create variant="atapi" property (if necessary)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * on the target's dev_info node. Currently, the sd target driver
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * is the only driver which refers to this property.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If the flag ata_id_debug is set also create the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the "ata" or "atapi" property on the target's dev_info node
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_prop_create(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *tgt_dip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf char *name)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_prop_create 0x%p 0x%p %s\n", tgt_dip, ata_drvp, name));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (strcmp("atapi", name) == 0) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ndi_prop_update_string(DDI_DEV_T_NONE, tgt_dip,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "variant", name);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc != DDI_PROP_SUCCESS)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_id_debug)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ndi_prop_update_byte_array(DDI_DEV_T_NONE, tgt_dip, name,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (uchar_t *)&ata_drvp->ad_id, sizeof (ata_drvp->ad_id));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc != DDI_PROP_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ERROR(("ata_prop_create failed, rc=%d\n", rc));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* *********************************************************************** */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* *********************************************************************** */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* *********************************************************************** */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * This state machine doesn't implement the ATAPI Optional Overlap
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * feature. You need that feature to efficiently support ATAPI
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * tape drives. See the 1394-ATA Tailgate spec (D97107), Figure 24,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * for an example of how to add the necessary additional NextActions
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * and NextStates to this FSM and the atapi_fsm, in order to support
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the Overlap Feature.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfuchar_t ata_ctlr_fsm_NextAction[ATA_CTLR_NSTATES][ATA_CTLR_NFUNCS] = {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* --------------------- next action --------------------- | - current - */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* start0 --- start1 ---- intr ------ fini --- reset --- */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ AC_START, AC_START, AC_NADA, AC_NADA, AC_RESET_I }, /* idle */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ AC_BUSY, AC_BUSY, AC_INTR, AC_FINI, AC_RESET_A }, /* active0 */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ AC_BUSY, AC_BUSY, AC_INTR, AC_FINI, AC_RESET_A }, /* active1 */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf};
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfuchar_t ata_ctlr_fsm_NextState[ATA_CTLR_NSTATES][ATA_CTLR_NFUNCS] = {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* --------------------- next state --------------------- | - current - */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* start0 --- start1 ---- intr ------ fini --- reset --- */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ AS_ACTIVE0, AS_ACTIVE1, AS_IDLE, AS_IDLE, AS_IDLE }, /* idle */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ AS_ACTIVE0, AS_ACTIVE0, AS_ACTIVE0, AS_IDLE, AS_ACTIVE0 }, /* active0 */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{ AS_ACTIVE1, AS_ACTIVE1, AS_ACTIVE1, AS_IDLE, AS_ACTIVE1 }, /* active1 */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf};
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_ctlr_fsm(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t fsm_func,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int *DoneFlgp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t action;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t current_state;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t next_state;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf current_state = ata_ctlp->ac_state;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf action = ata_ctlr_fsm_NextAction[current_state][fsm_func];
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf next_state = ata_ctlr_fsm_NextState[current_state][fsm_func];
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Set the controller's new state
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_state = next_state;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (action) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case AC_BUSY:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_BUSY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case AC_NADA:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_OKAY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case AC_START:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(ata_ctlp->ac_active_pktp == NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(ata_ctlp->ac_active_drvp == NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_active_pktp = ata_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_active_drvp = ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = (*ata_pktp->ap_start)(ata_ctlp, ata_drvp, ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc == ATA_FSM_RC_BUSY) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* the request didn't start, GHD will requeue it */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_state = AS_IDLE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_active_pktp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_active_drvp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case AC_INTR:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(ata_ctlp->ac_active_pktp != NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(ata_ctlp->ac_active_drvp != NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp = ata_ctlp->ac_active_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp = ata_ctlp->ac_active_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return ((*ata_pktp->ap_intr)(ata_ctlp, ata_drvp, ata_pktp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case AC_RESET_A: /* Reset, controller active */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(ata_ctlp->ac_active_pktp != NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(ata_ctlp->ac_active_drvp != NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* clean up the active request */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp = ata_ctlp->ac_active_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_DEV_RESET | AP_BUS_RESET;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* halt the DMA engine */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pktp->ap_pciide_dma) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pciide_dma_stop(ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_pciide_status_clear(ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Do a Software Reset to unwedge the bus */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_software_reset(ata_ctlp)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_BUSY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Then send a DEVICE RESET cmd to each ATAPI device */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_fsm_reset(ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_FINI);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case AC_RESET_I: /* Reset, controller idle */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Do a Software Reset to unwedge the bus */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_software_reset(ata_ctlp)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_BUSY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Then send a DEVICE RESET cmd to each ATAPI device */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atapi_fsm_reset(ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_OKAY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case AC_FINI:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * AC_FINI, check ARQ needs to be started or finished
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(action == AC_FINI);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(ata_ctlp->ac_active_pktp != NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(ata_ctlp->ac_active_drvp != NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The active request is done now.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Disconnect the request from the controller and
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * add it to the done queue.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp = ata_ctlp->ac_active_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp = ata_ctlp->ac_active_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If ARQ pkt is done, get ptr to original pkt and wrap it up.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pktp == ata_ctlp->ac_arq_pktp) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *arq_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ARQ(("ata_ctlr_fsm 0x%p ARQ done\n", ata_ctlp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf arq_pktp = ata_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp = ata_ctlp->ac_fault_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_fault_pktp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (arq_pktp->ap_flags & (AP_ERROR | AP_BUS_RESET))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_ARQ_ERROR;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_ARQ_OKAY;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto all_done;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#define AP_ARQ_NEEDED (AP_ARQ_ON_ERROR | AP_GOT_STATUS | AP_ERROR)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Start ARQ pkt if necessary
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((ata_pktp->ap_flags & AP_ARQ_NEEDED) == AP_ARQ_NEEDED &&
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ata_pktp->ap_status & ATS_ERR)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* set controller state back to active */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_state = current_state;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* try to start the ARQ pkt */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ata_start_arq(ata_ctlp, ata_drvp, ata_pktp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc == ATA_FSM_RC_BUSY) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ARQ(("ata_ctlr_fsm 0x%p ARQ BUSY\n", ata_ctlp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* let the target driver handle the problem */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_state = AS_IDLE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_active_pktp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_active_drvp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_fault_pktp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto all_done;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ARQ(("ata_ctlr_fsm 0x%p ARQ started\n", ata_ctlp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Normal completion, no error status, and not an ARQ pkt,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * just fall through.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfall_done:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * wrap everything up and tie a ribbon around it
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_active_pktp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_active_drvp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (APKT2GCMD(ata_pktp) != (gcmd_t *)0) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_complete(&ata_ctlp->ac_ccc, APKT2GCMD(ata_pktp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (DoneFlgp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *DoneFlgp = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ATA_FSM_RC_OKAY);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_start_arq(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *arq_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int bytes;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t senselen;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ARQ(("ata_start_arq 0x%p ARQ needed\n", ata_ctlp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Determine just the size of the Request Sense Data buffer within
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the scsi_arq_status structure.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#define SIZEOF_ARQ_HEADER (sizeof (struct scsi_arq_status) \
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf - sizeof (struct scsi_extended_sense))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf senselen = ata_pktp->ap_statuslen - SIZEOF_ARQ_HEADER;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(senselen > 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* save ptr to original pkt */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_fault_pktp = ata_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* switch the controller's active pkt to the ARQ pkt */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf arq_pktp = ata_ctlp->ac_arq_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_active_pktp = arq_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* finish initializing the ARQ CDB */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp->ac_arq_cdb[1] = ata_drvp->ad_lun << 4;
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China ata_ctlp->ac_arq_cdb[4] = (uchar_t)senselen;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* finish initializing the ARQ pkt */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf arq_pktp->ap_v_addr = (caddr_t)&ata_pktp->ap_scbp->sts_sensedata;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf arq_pktp->ap_resid = senselen;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf arq_pktp->ap_flags = AP_ATAPI | AP_READ;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf arq_pktp->ap_cdb_pad =
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ((unsigned)(ata_drvp->ad_cdb_len - arq_pktp->ap_cdb_len)) >> 1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf bytes = min(senselen, ATAPI_MAX_BYTES_PER_DRQ);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf arq_pktp->ap_hicyl = (uchar_t)(bytes >> 8);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf arq_pktp->ap_lwcyl = (uchar_t)bytes;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * This packet is shared by all drives on this controller
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * therefore we need to init the drive number on every ARQ.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf arq_pktp->ap_hd = ata_drvp->ad_drive_bits;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* start it up */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return ((*arq_pktp->ap_start)(ata_ctlp, ata_drvp, arq_pktp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * reset the bus
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_reset_bus(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int watchdog;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t drive;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t fsm_func;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int DoneFlg = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Do a Software Reset to unwedge the bus, and send
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ATAPI DEVICE RESET to each ATAPI drive.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf fsm_func = ATA_FSM_RESET;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (watchdog = ata_reset_bus_watchdog; watchdog > 0; watchdog--) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (ata_ctlr_fsm(fsm_func, ata_ctlp, NULL, NULL,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf &DoneFlg)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_OKAY:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto fsm_done;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_BUSY:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_INTR:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf fsm_func = ATA_FSM_INTR;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_FINI:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf fsm_func = ATA_FSM_FINI;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_reset_bus: watchdog\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlffsm_done:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Reinitialize the ATA drives
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (drive = 0; drive < ATA_MAXTARG; drive++) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((ata_drvp = CTL2DRV(ata_ctlp, drive, 0)) == NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ATAPIDRV(ata_drvp))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Reprogram the Read/Write Multiple block factor
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * and current geometry into the drive.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_disk_setup_parms(ata_ctlp, ata_drvp))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* If DoneFlg is TRUE, it means that ghd_complete() function */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* has been already called. In this case ignore any errors and */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* return TRUE to the caller, otherwise return the value of rc */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* to the caller */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (DoneFlg)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Low level routine to toggle the Software Reset bit
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_software_reset(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
9f49ae270d37efd5c5270cb8046b4229b5380021mlf hrtime_t deadline;
9f49ae270d37efd5c5270cb8046b4229b5380021mlf uint_t usecs_left;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_reset_bus entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* disable interrupts and turn the software reset bit on */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl2, ata_ctlp->ac_devctl, (ATDC_D3 | ATDC_SRST));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* why 30 milliseconds, the ATA/ATAPI-4 spec says 5 usec. */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drv_usecwait(30000);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* turn the software reset bit back off */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl2, ata_ctlp->ac_devctl, ATDC_D3);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Wait for the controller to assert BUSY status.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * I don't think 300 msecs is correct. The ATA/ATAPI-4
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * spec says 400 nsecs, (and 2 msecs if device
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * was in sleep mode; but we don't put drives to sleep
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * so it probably doesn't matter).
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drv_usecwait(300000);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If drive 0 exists the test for completion is simple
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf deadline = gethrtime() + ((hrtime_t)31 * NANOSEC);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (CTL2DRV(ata_ctlp, 0, 0)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto wait_for_not_busy;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(CTL2DRV(ata_ctlp, 1, 0) != NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * This must be a single device configuration, with drive 1
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * only. This complicates the test for completion because
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * issuing the software reset just caused drive 1 to
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * deselect. With drive 1 deselected, if I just read the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * status register to test the BSY bit I get garbage, but
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * I can't re-select drive 1 until I'm certain the BSY bit
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * is de-asserted. Catch-22.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * In ATA/ATAPI-4, rev 15, section 9.16.2, it says to handle
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * this situation like this:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* give up if the drive doesn't settle within 31 seconds */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf while (gethrtime() < deadline) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * delay 10msec each time around the loop
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drv_usecwait(10000);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * try to select drive 1
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, ATDH_DRIVE1);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_sect, 0x55);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_sect, 0xaa);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ddi_get8(io_hdl1, ata_ctlp->ac_sect) != 0xaa)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_count, 0x55);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_put8(io_hdl1, ata_ctlp->ac_count, 0xaa);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ddi_get8(io_hdl1, ata_ctlp->ac_count) != 0xaa)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto wait_for_not_busy;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfwait_for_not_busy:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
9f49ae270d37efd5c5270cb8046b4229b5380021mlf * Now wait up to 31 seconds for BUSY to clear.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf usecs_left = (deadline - gethrtime()) / 1000;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_wait3(io_hdl2, ata_ctlp->ac_ioaddr2, 0, ATS_BSY,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATS_ERR, ATS_BSY, ATS_DF, ATS_BSY, usecs_left);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * DDI interrupt handler
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic uint_t
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_intr(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t arg)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int one_shot = 1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp = (ata_ctl_t *)arg;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (ghd_intr(&ata_ctlp->ac_ccc, (void *)&one_shot));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * GHD ccc_get_status callback
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_get_status(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *hba_handle,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *intr_status)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp = (ata_ctl_t *)hba_handle;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t status;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_get_status entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ignore interrupts before ata_attach completes
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!(ata_ctlp->ac_flags & AC_ATTACHED))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * can't be interrupt pending if nothing active
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (ata_ctlp->ac_state) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case AS_IDLE:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case AS_ACTIVE0:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case AS_ACTIVE1:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(ata_ctlp->ac_active_drvp != NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(ata_ctlp->ac_active_pktp != NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If this is a PCI-IDE controller, check the PCI-IDE controller's
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * interrupt status latch. But don't clear it yet.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * AC_BMSTATREG_PIO_BROKEN flag is used currently for
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * CMD chips with device id 0x646. Since the interrupt bit on
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Bus master IDE register is not usable when in PIO mode,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * this chip is treated as a legacy device for interrupt
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * indication. The following code for CMD
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * chips may need to be revisited when we enable support for dma.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * CHANGE: DMA is not disabled for these devices. BM intr bit is
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * checked only if there was DMA used or BM intr is useable on PIO,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * else treat it as before - as legacy device.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((ata_ctlp->ac_pciide) &&
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ((ata_ctlp->ac_pciide_bm != FALSE) &&
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ((ata_ctlp->ac_active_pktp->ap_pciide_dma == TRUE) ||
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf !(ata_ctlp->ac_flags & AC_BMSTATREG_PIO_BROKEN)))) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_pciide_status_pending(ata_ctlp))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Interrupts from legacy ATA/IDE controllers are
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * edge-triggered but the dumb legacy ATA/IDE controllers
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * and drives don't have an interrupt status bit.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Use a one_shot variable to make sure we only return
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * one status per interrupt.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (intr_status != NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int *one_shot = (int *)intr_status;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (*one_shot == 1)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *one_shot = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* check if device is still busy */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf status = ddi_get8(ata_ctlp->ac_iohandle2, ata_ctlp->ac_altstatus);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (status & ATS_BSY)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * get the current status and clear the IRQ
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_get_status_clear_intr(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t status;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Here's where we clear the PCI-IDE interrupt latch. If this
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * request used DMA mode then we also have to check and clear
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the DMA error latch at the same time.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pktp->ap_pciide_dma) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pciide_status_dmacheck_clear(ata_ctlp))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_flags |= AP_ERROR | AP_TRAN_ERROR;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else if ((ata_ctlp->ac_pciide) &&
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf !(ata_ctlp->ac_flags & AC_BMSTATREG_PIO_BROKEN)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Some requests don't use DMA mode and therefore won't
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * set the DMA error latch, but we still have to clear
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the interrupt latch.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Controllers with broken BM intr in PIO mode do not go
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * through this path.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ata_pciide_status_clear(ata_ctlp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * this clears the drive's interrupt
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf status = ddi_get8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_status);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_get_status_clear_intr: 0x%x\n", status));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (status);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * GHD interrupt handler
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* ARGSUSED */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_process_intr(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *hba_handle,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *intr_status)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp = (ata_ctl_t *)hba_handle;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int watchdog;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t fsm_func;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_process_intr entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * process the ATA or ATAPI interrupt
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf fsm_func = ATA_FSM_INTR;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (watchdog = ata_process_intr_watchdog; watchdog > 0; watchdog--) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ata_ctlr_fsm(fsm_func, ata_ctlp, NULL, NULL, NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (rc) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_OKAY:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_BUSY: /* wait for the next interrupt */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_INTR: /* re-invoke the FSM */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf fsm_func = ATA_FSM_INTR;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_FINI: /* move a request to done Q */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf fsm_func = ATA_FSM_FINI;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_process_intr: watchdog\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * GHD ccc_hba_start callback
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_hba_start(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *hba_handle,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *gcmdp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uchar_t fsm_func;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int request_started;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int watchdog;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_TRACE(("ata_hba_start entered\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctlp = (ata_ctl_t *)hba_handle;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_active_drvp != NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_hba_start drvp not null\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_active_pktp != NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_hba_start pktp not null\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp = GCMD2APKT(gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp = GCMD2DRV(gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * which drive?
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_drvp->ad_targ == 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf fsm_func = ATA_FSM_START0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf fsm_func = ATA_FSM_START1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * start the request
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf request_started = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (watchdog = ata_hba_start_watchdog; watchdog > 0; watchdog--) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (ata_ctlr_fsm(fsm_func, ata_ctlp, ata_drvp, ata_pktp,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf NULL)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_OKAY:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf request_started = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto fsm_done;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_BUSY:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* if first time, tell GHD to requeue the request */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto fsm_done;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_INTR:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The start function polled for the next
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * bus phase, now fake an interrupt to process
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the next action.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf request_started = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf fsm_func = ATA_FSM_INTR;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case ATA_FSM_RC_FINI: /* move request to the done queue */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf request_started = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf fsm_func = ATA_FSM_FINI;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_WARN(("ata_hba_start: watchdog\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlffsm_done:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (request_started);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_check_pciide_blacklist(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *dip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t flags)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ushort_t vendorid;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ushort_t deviceid;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf pcibl_t *blp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int *propp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t count;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf vendorid = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf DDI_PROP_DONTPASS, "vendor-id", 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf deviceid = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf DDI_PROP_DONTPASS, "device-id", 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * first check for a match in the "pci-ide-blacklist" property
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "pci-ide-blacklist", &propp, &count);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc == DDI_PROP_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf count = (count * sizeof (uint_t)) / sizeof (pcibl_t);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf blp = (pcibl_t *)propp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf while (count--) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* check for matching ID */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((vendorid & blp->b_vmask)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf != (blp->b_vendorid & blp->b_vmask)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf blp++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((deviceid & blp->b_dmask)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf != (blp->b_deviceid & blp->b_dmask)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf blp++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* got a match */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (blp->b_flags & flags) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_prop_free(propp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_prop_free(propp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_prop_free(propp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * then check the built-in blacklist
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (blp = ata_pciide_blacklist; blp->b_vendorid; blp++) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((vendorid & blp->b_vmask) != blp->b_vendorid)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((deviceid & blp->b_dmask) != blp->b_deviceid)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!(blp->b_flags & flags))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_check_drive_blacklist(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf struct ata_id *aidp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t flags)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf atabl_t *blp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
744a060193833d1e3b4db51fd9a2ecd996659613Ling Albert Ke for (blp = ata_drive_blacklist; blp->b_model != NULL; blp++) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!ata_strncmp(blp->b_model, aidp->ai_model,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf sizeof (aidp->ai_model)))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
744a060193833d1e3b4db51fd9a2ecd996659613Ling Albert Ke if (blp->b_fw != NULL) {
744a060193833d1e3b4db51fd9a2ecd996659613Ling Albert Ke if (!ata_strncmp(blp->b_fw, aidp->ai_fw,
744a060193833d1e3b4db51fd9a2ecd996659613Ling Albert Ke sizeof (aidp->ai_fw)))
744a060193833d1e3b4db51fd9a2ecd996659613Ling Albert Ke continue;
744a060193833d1e3b4db51fd9a2ecd996659613Ling Albert Ke }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (blp->b_flags & flags)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Queue a request to perform some sort of internally
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * generated command. When this request packet reaches
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the front of the queue (*func)() is invoked.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_queue_cmd(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int (*func)(ata_ctl_t *, ata_drv_t *, ata_pkt_t *),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *arg,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gtgt_t *gtgtp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pkt_t *ata_pktp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *gcmdp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!(gcmdp = ghd_gcmd_alloc(gtgtp, sizeof (*ata_pktp), TRUE))) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ADBG_ERROR(("atapi_id_update alloc failed\n"));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* set the back ptr from the ata_pkt to the gcmd_t */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp = GCMD2APKT(gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_gcmdp = gcmdp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_hd = ata_drvp->ad_drive_bits;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_bytes_per_block = ata_drvp->ad_bytes_per_block;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * over-ride the default start function
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp = GCMD2APKT(gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_start = func;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_complete = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_pktp->ap_v_addr = (caddr_t)arg;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * add it to the queue, when it gets to the front the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ap_start function is called.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ghd_transport(&ata_ctlp->ac_ccc, gcmdp, gcmdp->cmd_gtgtp,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf 0, TRUE, NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc != TRAN_ACCEPT) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* this should never, ever happen */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_pktp->ap_flags & AP_ERROR)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Check if this drive has the "revert to defaults" bug
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * PSARC 2001/500 and 2001/xxx - check for the properties
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ata-revert-to-defaults and atarvrt-<diskmodel> before
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * examining the blacklist.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * <diskmodel> is made from the model number reported by Identify Drive
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * with uppercase letters converted to lowercase and all characters
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * except letters, digits, ".", "_", and "-" deleted.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Return value:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * TRUE: enable revert to defaults
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * FALSE: disable revert to defaults
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * NOTE: revert to power on defaults that includes reverting to MDMA
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * mode is allowed by ATA-6 & ATA-7 specs.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Therefore drives exhibiting this behaviour are not violating the spec.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Furthermore, the spec explicitly says that after the soft reset
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * host should check the current setting of the device features.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Correctly working BIOS would therefore reprogram either the drive
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * and/or the host controller to match transfer modes.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Devices with ATA_BL_NORVRT flag will be removed from
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the ata_blacklist.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The default behaviour will be - no revert to power-on defaults
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * for all devices. The property is retained in case the user
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * explicitly requests revert-to-defaults before reboot.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#define ATA_REVERT_PROP_PREFIX "revert-"
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#define ATA_REVERT_PROP_GLOBAL "ata-revert-to-defaults"
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* room for prefix + model number + terminating NUL character */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#define PROP_BUF_SIZE (sizeof (ATA_REVERT_PROP_PREFIX) + \
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf sizeof (aidp->ai_model) + 1)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#define PROP_LEN_MAX (31)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_check_revert_to_defaults(
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drv_t *ata_drvp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf struct ata_id *aidp = &ata_drvp->ad_id;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf char prop_buf[PROP_BUF_SIZE];
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int i, j;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int propval;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* put prefix into the buffer */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) strcpy(prop_buf, ATA_REVERT_PROP_PREFIX);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf j = strlen(prop_buf);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* append the model number, leaving out invalid characters */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (i = 0; i < sizeof (aidp->ai_model); ++i) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf char c = aidp->ai_model[i];
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (c >= 'A' && c <= 'Z') /* uppercase -> lower */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf c = c - 'A' + 'a';
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ||
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf c == '.' || c == '_' || c == '-')
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf prop_buf[j++] = c;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (c == '\0')
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* make sure there's a terminating NUL character */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (j >= PROP_LEN_MAX)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf j = PROP_LEN_MAX;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf prop_buf[j] = '\0';
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* look for a disk-specific "revert" property" */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf propval = ddi_getprop(DDI_DEV_T_ANY, ata_ctlp->ac_dip,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf DDI_PROP_DONTPASS, prop_buf, -1);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (propval == 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else if (propval != -1)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* look for a global "revert" property" */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf propval = ddi_getprop(DDI_DEV_T_ANY, ata_ctlp->ac_dip,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf 0, ATA_REVERT_PROP_GLOBAL, -1);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (propval == 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else if (propval != -1)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfvoid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_show_transfer_mode(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int i;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_ctlp->ac_pciide_bm == FALSE ||
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ata_drvp->ad_pciide_dma != ATA_DMA_ON) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_cntrl_DMA_sel_msg) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT((
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "?\tATA DMA off: %s\n", ata_cntrl_DMA_sel_msg));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else if (ata_dev_DMA_sel_msg) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\tATA DMA off: %s\n", ata_dev_DMA_sel_msg));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\tPIO mode %d selected\n",
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (ata_drvp->ad_id.ai_advpiomode & ATAC_ADVPIO_4_SUP) ==
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATAC_ADVPIO_4_SUP ? 4 : 3));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Using DMA */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_drvp->ad_id.ai_dworddma & ATAC_MDMA_SEL_MASK) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Rely on the fact that either dwdma or udma is
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * selected, not both.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT(("?\tMultiwordDMA mode %d selected\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ata_drvp->ad_id.ai_dworddma & ATAC_MDMA_2_SEL) ==
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAC_MDMA_2_SEL ? 2 :
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (ata_drvp->ad_id.ai_dworddma & ATAC_MDMA_1_SEL) ==
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATAC_MDMA_1_SEL ? 1 : 0));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (i = 0; i <= 6; i++) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ata_drvp->ad_id.ai_ultradma &
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (1 << (i + 8))) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ATAPRT((
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "?\tUltraDMA mode %d selected\n",
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf i));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Controller-specific operation pointers.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Should be extended as needed - init only for now
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstruct ata_ctl_spec_ops {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t (*cs_init)(dev_info_t *, ushort_t, ushort_t); /* ctlr init */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf};
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstruct ata_ctl_spec {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ushort_t cs_vendor_id;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ushort_t cs_device_id;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf struct ata_ctl_spec_ops *cs_ops;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf};
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* Sil3XXX-specific functions (init only for now) */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstruct ata_ctl_spec_ops sil3xxx_ops = {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf &sil3xxx_init_controller /* Sil3XXX cntrl initialization */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf};
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstruct ata_ctl_spec ata_cntrls_spec[] = {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf {0x1095, 0x3114, &sil3xxx_ops},
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf {0x1095, 0x3512, &sil3xxx_ops},
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf {0x1095, 0x3112, &sil3xxx_ops},
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf {0, 0, NULL} /* List must end with cs_ops set to NULL */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf};
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Do controller specific initialization if necessary.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Pick-up controller specific functions.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_spec_init_controller(dev_info_t *dip)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ushort_t vendor_id;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ushort_t device_id;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf struct ata_ctl_spec *ctlsp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf vendor_id = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf DDI_PROP_DONTPASS, "vendor-id", 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf device_id = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf DDI_PROP_DONTPASS, "device-id", 0);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Locate controller specific ops, if they exist */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ctlsp = ata_cntrls_spec;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf while (ctlsp->cs_ops != NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ctlsp->cs_vendor_id == vendor_id &&
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ctlsp->cs_device_id == device_id)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ctlsp++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ctlsp->cs_ops != NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ctlsp->cs_ops->cs_init != NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Initialize controller */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((*(ctlsp->cs_ops->cs_init))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (dip, vendor_id, device_id) != TRUE) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cmn_err(CE_WARN,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "pci%4x,%4x cntrl specific "
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "initialization failed",
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf vendor_id, device_id);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * this routine works like ddi_prop_get_int, except that it works on
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * a string property that contains ascii representations
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * of an integer.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If the property is not found, the default value is returned.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfata_prop_lookup_int(dev_t match_dev, dev_info_t *dip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t flags, char *name, int defvalue)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf char *bufp, *cp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc = defvalue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int proprc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf proprc = ddi_prop_lookup_string(match_dev, dip,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf flags, name, &bufp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (proprc == DDI_PROP_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cp = bufp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = stoi(&cp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_prop_free(bufp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * see if property is encoded as an int instead of string.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ddi_prop_get_int(match_dev, dip, flags, name, defvalue);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Initialize the power management components
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfata_init_pm(dev_info_t *dip)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char pmc_name[16];
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char *pmc[] = {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf NULL,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "0=Sleep (PCI D3 State)",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "3=PowerOn (PCI D0 State)",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf NULL
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf };
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int instance;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctl_t *ata_ctlp;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf instance = ddi_get_instance(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp = ddi_get_soft_state(ata_state, instance);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_pm_support = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* check PCI capabilities */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!ata_is_pci(dip))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) sprintf(pmc_name, "NAME=ata%d", instance);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf pmc[0] = pmc_name;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#ifdef ATA_USE_AUTOPM
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "pm-components", pmc, 3) != DDI_PROP_SUCCESS) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_pm_support = 1;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_pm_level = PM_LEVEL_D0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATA_BUSY_COMPONENT(dip, 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ATA_RAISE_POWER(dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-components");
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATA_IDLE_COMPONENT(dip, 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * resume the hard drive
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfata_resume_drive(ata_drv_t *ata_drvp)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int drive_type;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf struct ata_id id;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ADBG_TRACE(("ata_resume_drive entered\n"));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf drive_type = ata_drive_type(ata_drvp->ad_drive_bits,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_iohandle1, ata_ctlp->ac_ioaddr1,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf &id);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (drive_type == ATA_DEV_NONE)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!ATAPIDRV(ata_drvp)) {
62c8caf3fac65817982e780c1efa988846153bf0Ada /* Reset Ultra DMA mode */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg ata_reset_dma_mode(ata_drvp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!ata_disk_setup_parms(ata_ctlp, ata_drvp))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return;
62c8caf3fac65817982e780c1efa988846153bf0Ada } else {
b44e05abb9e60a162807784ce70b2998c0cbe51eAda (void) atapi_init_drive(ata_drvp);
fe072f421ec51952432306add7d50852ad1921b2Ada if (ata_drvp->ad_dma_mode != 0) {
fe072f421ec51952432306add7d50852ad1921b2Ada (void) atapi_reset_dma_mode(ata_drvp, FALSE);
fe072f421ec51952432306add7d50852ad1921b2Ada if (!ata_check_dma_mode(ata_drvp))
fe072f421ec51952432306add7d50852ad1921b2Ada atapi_reset_dma_mode(ata_drvp, TRUE);
fe072f421ec51952432306add7d50852ad1921b2Ada if (ata_drvp->ad_id.ai_ultradma !=
fe072f421ec51952432306add7d50852ad1921b2Ada ata_drvp->ad_dma_mode) {
fe072f421ec51952432306add7d50852ad1921b2Ada ata_drvp->ad_pciide_dma = ATA_DMA_OFF;
fe072f421ec51952432306add7d50852ad1921b2Ada } else {
fe072f421ec51952432306add7d50852ad1921b2Ada ata_drvp->ad_pciide_dma = ATA_DMA_ON;
fe072f421ec51952432306add7d50852ad1921b2Ada }
fe072f421ec51952432306add7d50852ad1921b2Ada }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
62c8caf3fac65817982e780c1efa988846153bf0Ada (void) ata_set_feature(ata_ctlp, ata_drvp, ATSF_DIS_REVPOD, 0);
62c8caf3fac65817982e780c1efa988846153bf0Ada
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * resume routine, it will be run when get the command
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * DDI_RESUME at attach(9E) from system power management
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfata_resume(dev_info_t *dip)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int instance;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctl_t *ata_ctlp;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_acc_handle_t io_hdl2;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf caddr_t ioaddr2;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf instance = ddi_get_instance(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp = ddi_get_soft_state(ata_state, instance);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!ata_ctlp->ac_pm_support)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ata_ctlp->ac_pm_level == PM_LEVEL_D0)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_SUCCESS);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATA_BUSY_COMPONENT(dip, 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ATA_RAISE_POWER(dip, 0, PM_LEVEL_D0) == DDI_FAILURE)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ATA_IDLE_COMPONENT(dip, 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* enable interrupts from the device */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf io_hdl2 = ata_ctlp->ac_iohandle2;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ioaddr2 = ata_ctlp->ac_ioaddr2;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_put8(io_hdl2, (uchar_t *)ioaddr2 + AT_DEVCTL, ATDC_D3);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_pm_level = PM_LEVEL_D0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_SUCCESS);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * suspend routine, it will be run when get the command
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * DDI_SUSPEND at detach(9E) from system power management
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfata_suspend(dev_info_t *dip)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int instance;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctl_t *ata_ctlp;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_acc_handle_t io_hdl2;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf instance = ddi_get_instance(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp = ddi_get_soft_state(ata_state, instance);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!ata_ctlp->ac_pm_support)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ata_ctlp->ac_pm_level == PM_LEVEL_D3)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_SUCCESS);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* disable interrupts and turn the software reset bit on */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf io_hdl2 = ata_ctlp->ac_iohandle2;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_put8(io_hdl2, ata_ctlp->ac_devctl, (ATDC_D3 | ATDC_SRST));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) ata_reset_bus(ata_ctlp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) ata_change_power(dip, ATC_SLEEP);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_pm_level = PM_LEVEL_D3;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_SUCCESS);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfint ata_save_pci_config = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * ata specific power management entry point, it was
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * used to change the power management component
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfata_power(dev_info_t *dip, int component, int level)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int instance;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctl_t *ata_ctlp;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf uint8_t cmd;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ADBG_TRACE(("ata_power entered, component = %d, level = %d\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf component, level));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf instance = ddi_get_instance(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp = ddi_get_soft_state(ata_state, instance);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ata_ctlp == NULL || component != 0)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!ata_ctlp->ac_pm_support)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
8c97a06b88a7f040b7d72941ca32323bb75cfec7Ada if (ata_ctlp->ac_pm_level == level)
8c97a06b88a7f040b7d72941ca32323bb75cfec7Ada return (DDI_SUCCESS);
8c97a06b88a7f040b7d72941ca32323bb75cfec7Ada
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf switch (level) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case PM_LEVEL_D0:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ata_save_pci_config)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) pci_restore_config_regs(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_pm_level = PM_LEVEL_D0;
dcafa541382944b24abd3a40c357b47e04f314e2randyf cmd = ATC_IDLE_IMMED;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf break;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case PM_LEVEL_D3:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ata_save_pci_config)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) pci_save_config_regs(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp->ac_pm_level = PM_LEVEL_D3;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cmd = ATC_SLEEP;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf break;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf default:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (ata_change_power(dip, cmd));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * sent commands to ata controller to change the power level
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfata_change_power(dev_info_t *dip, uint8_t cmd)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int instance;
fe072f421ec51952432306add7d50852ad1921b2Ada ata_ctl_t *ata_ctlp;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_drv_t *ata_drvp;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf uchar_t targ;
fe072f421ec51952432306add7d50852ad1921b2Ada struct ata_id id;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf uchar_t lun;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf uchar_t lastlun;
8c97a06b88a7f040b7d72941ca32323bb75cfec7Ada struct ata_id *aidp;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ADBG_TRACE(("ata_change_power entered, cmd = %d\n", cmd));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf instance = ddi_get_instance(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_ctlp = ddi_get_soft_state(ata_state, instance);
8c97a06b88a7f040b7d72941ca32323bb75cfec7Ada
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Issue command on each disk device on the bus.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
62c8caf3fac65817982e780c1efa988846153bf0Ada if (cmd == ATC_SLEEP) {
62c8caf3fac65817982e780c1efa988846153bf0Ada for (targ = 0; targ < ATA_MAXTARG; targ++) {
62c8caf3fac65817982e780c1efa988846153bf0Ada ata_drvp = CTL2DRV(ata_ctlp, targ, 0);
62c8caf3fac65817982e780c1efa988846153bf0Ada if (ata_drvp == NULL)
62c8caf3fac65817982e780c1efa988846153bf0Ada continue;
fe072f421ec51952432306add7d50852ad1921b2Ada if (ata_drvp->ad_dma_cap == 0 &&
fe072f421ec51952432306add7d50852ad1921b2Ada ata_drvp->ad_pciide_dma == ATA_DMA_ON) {
fe072f421ec51952432306add7d50852ad1921b2Ada aidp = &ata_drvp->ad_id;
fe072f421ec51952432306add7d50852ad1921b2Ada if ((aidp->ai_validinfo & ATAC_VALIDINFO_83) &&
fe072f421ec51952432306add7d50852ad1921b2Ada (aidp->ai_ultradma & ATAC_UDMA_SEL_MASK)) {
fe072f421ec51952432306add7d50852ad1921b2Ada ata_drvp->ad_dma_cap =
fe072f421ec51952432306add7d50852ad1921b2Ada ATA_DMA_ULTRAMODE;
fe072f421ec51952432306add7d50852ad1921b2Ada ata_drvp->ad_dma_mode =
fe072f421ec51952432306add7d50852ad1921b2Ada aidp->ai_ultradma;
fe072f421ec51952432306add7d50852ad1921b2Ada } else if (aidp->ai_dworddma &
fe072f421ec51952432306add7d50852ad1921b2Ada ATAC_MDMA_SEL_MASK) {
fe072f421ec51952432306add7d50852ad1921b2Ada ata_drvp->ad_dma_cap =
fe072f421ec51952432306add7d50852ad1921b2Ada ATA_DMA_MWORDMODE;
fe072f421ec51952432306add7d50852ad1921b2Ada ata_drvp->ad_dma_mode =
fe072f421ec51952432306add7d50852ad1921b2Ada aidp->ai_dworddma;
fe072f421ec51952432306add7d50852ad1921b2Ada }
8c97a06b88a7f040b7d72941ca32323bb75cfec7Ada }
62c8caf3fac65817982e780c1efa988846153bf0Ada if (ata_drive_type(ata_drvp->ad_drive_bits,
62c8caf3fac65817982e780c1efa988846153bf0Ada ata_ctlp->ac_iohandle1, ata_ctlp->ac_ioaddr1,
62c8caf3fac65817982e780c1efa988846153bf0Ada ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2,
62c8caf3fac65817982e780c1efa988846153bf0Ada &id) != ATA_DEV_DISK)
62c8caf3fac65817982e780c1efa988846153bf0Ada continue;
62c8caf3fac65817982e780c1efa988846153bf0Ada (void) ata_flush_cache(ata_ctlp, ata_drvp);
62c8caf3fac65817982e780c1efa988846153bf0Ada if (!ata_command(ata_ctlp, ata_drvp, TRUE, TRUE,
62c8caf3fac65817982e780c1efa988846153bf0Ada 5 * 1000000, cmd, 0, 0, 0, 0, 0, 0)) {
62c8caf3fac65817982e780c1efa988846153bf0Ada cmn_err(CE_WARN, "!ata_controller - Can not "
62c8caf3fac65817982e780c1efa988846153bf0Ada "put drive %d in to power mode %u",
62c8caf3fac65817982e780c1efa988846153bf0Ada targ, cmd);
62c8caf3fac65817982e780c1efa988846153bf0Ada (void) ata_devo_reset(dip, DDI_RESET_FORCE);
62c8caf3fac65817982e780c1efa988846153bf0Ada return (DDI_FAILURE);
62c8caf3fac65817982e780c1efa988846153bf0Ada }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_SUCCESS);
62c8caf3fac65817982e780c1efa988846153bf0Ada }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
62c8caf3fac65817982e780c1efa988846153bf0Ada (void) ata_software_reset(ata_ctlp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf for (targ = 0; targ < ATA_MAXTARG; targ++) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_drvp = CTL2DRV(ata_ctlp, targ, 0);
62c8caf3fac65817982e780c1efa988846153bf0Ada if (ata_drvp == NULL)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf continue;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_resume_drive(ata_drvp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ATAPIDRV(ata_drvp))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf lastlun = ata_drvp->ad_id.ai_lastlun;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf else
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf lastlun = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!ata_enable_atapi_luns)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf lastlun = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf for (lun = 1; lun <= lastlun && lun < ATA_MAXLUN; lun++) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_drvp = CTL2DRV(ata_ctlp, targ, lun);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ata_drvp != NULL)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ata_resume_drive(ata_drvp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_SUCCESS);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * return 1 when ata controller is a pci device,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * otherwise return 0
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfata_is_pci(dev_info_t *dip)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int rc;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char *bufp;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int ispci;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf rc = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(dip),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf DDI_PROP_DONTPASS, "device_type", &bufp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (rc != DDI_PROP_SUCCESS) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ADBG_ERROR(("ata_is_pci !device_type\n"));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ispci = (strcmp(bufp, "pci-ide") == 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_prop_free(bufp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (ispci);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
5fb86bae323519d98a63f5829df4b849f1fe1598ml
5fb86bae323519d98a63f5829df4b849f1fe1598ml/*
5fb86bae323519d98a63f5829df4b849f1fe1598ml * Disable DMA for this drive
5fb86bae323519d98a63f5829df4b849f1fe1598ml */
5fb86bae323519d98a63f5829df4b849f1fe1598mlstatic void
5fb86bae323519d98a63f5829df4b849f1fe1598mlata_disable_DMA(ata_drv_t *ata_drvp)
5fb86bae323519d98a63f5829df4b849f1fe1598ml{
5fb86bae323519d98a63f5829df4b849f1fe1598ml struct ata_id *aidp;
5fb86bae323519d98a63f5829df4b849f1fe1598ml char buf[sizeof (aidp->ai_model) +2];
5fb86bae323519d98a63f5829df4b849f1fe1598ml int i;
5fb86bae323519d98a63f5829df4b849f1fe1598ml
5fb86bae323519d98a63f5829df4b849f1fe1598ml if (ata_drvp == NULL)
5fb86bae323519d98a63f5829df4b849f1fe1598ml return;
5fb86bae323519d98a63f5829df4b849f1fe1598ml
5fb86bae323519d98a63f5829df4b849f1fe1598ml if (ata_drvp->ad_pciide_dma == ATA_DMA_OFF)
5fb86bae323519d98a63f5829df4b849f1fe1598ml return;
5fb86bae323519d98a63f5829df4b849f1fe1598ml
5fb86bae323519d98a63f5829df4b849f1fe1598ml ata_drvp->ad_pciide_dma = ATA_DMA_OFF;
5fb86bae323519d98a63f5829df4b849f1fe1598ml
5fb86bae323519d98a63f5829df4b849f1fe1598ml /* Print the message */
5fb86bae323519d98a63f5829df4b849f1fe1598ml buf[0] = '\0';
5fb86bae323519d98a63f5829df4b849f1fe1598ml aidp = &ata_drvp->ad_id;
5fb86bae323519d98a63f5829df4b849f1fe1598ml if (aidp != NULL) {
5fb86bae323519d98a63f5829df4b849f1fe1598ml (void) strncpy(buf, aidp->ai_model, sizeof (aidp->ai_model));
5fb86bae323519d98a63f5829df4b849f1fe1598ml buf[sizeof (aidp->ai_model) -1] = '\0';
5fb86bae323519d98a63f5829df4b849f1fe1598ml for (i = sizeof (aidp->ai_model) - 2; buf[i] == ' '; i--)
5fb86bae323519d98a63f5829df4b849f1fe1598ml buf[i] = '\0';
5fb86bae323519d98a63f5829df4b849f1fe1598ml }
5fb86bae323519d98a63f5829df4b849f1fe1598ml cmn_err(CE_CONT,
5fb86bae323519d98a63f5829df4b849f1fe1598ml "?DMA disabled on %s target=%d, lun=%d due to DMA errors,",
5fb86bae323519d98a63f5829df4b849f1fe1598ml buf, ata_drvp->ad_targ, ata_drvp->ad_lun);
5fb86bae323519d98a63f5829df4b849f1fe1598ml cmn_err(CE_CONT, "?most likely due to the CF-to-IDE adapter.");
5fb86bae323519d98a63f5829df4b849f1fe1598ml}
c8531848467a8747b65b91ab83c4b57f4c000848yt
c8531848467a8747b65b91ab83c4b57f4c000848yt/*
c8531848467a8747b65b91ab83c4b57f4c000848yt * Check and select DMA mode
c8531848467a8747b65b91ab83c4b57f4c000848yt *
c8531848467a8747b65b91ab83c4b57f4c000848yt * TRUE is returned when set feature is called successfully,
c8531848467a8747b65b91ab83c4b57f4c000848yt * otherwise return FALSE
c8531848467a8747b65b91ab83c4b57f4c000848yt */
c8531848467a8747b65b91ab83c4b57f4c000848ytint
c8531848467a8747b65b91ab83c4b57f4c000848ytata_set_dma_mode(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp)
c8531848467a8747b65b91ab83c4b57f4c000848yt{
c8531848467a8747b65b91ab83c4b57f4c000848yt struct ata_id *aidp;
c8531848467a8747b65b91ab83c4b57f4c000848yt int mode, rval = FALSE;
c8531848467a8747b65b91ab83c4b57f4c000848yt uint8_t subcmd;
c8531848467a8747b65b91ab83c4b57f4c000848yt
c8531848467a8747b65b91ab83c4b57f4c000848yt aidp = &ata_drvp->ad_id;
c8531848467a8747b65b91ab83c4b57f4c000848yt
c8531848467a8747b65b91ab83c4b57f4c000848yt /* Return directly if DMA is not supported */
c8531848467a8747b65b91ab83c4b57f4c000848yt if (!(aidp->ai_cap & ATAC_DMA_SUPPORT))
c8531848467a8747b65b91ab83c4b57f4c000848yt return (rval);
c8531848467a8747b65b91ab83c4b57f4c000848yt
8c97a06b88a7f040b7d72941ca32323bb75cfec7Ada /* Return if DMA mode is already selected */
8c97a06b88a7f040b7d72941ca32323bb75cfec7Ada if (((aidp->ai_validinfo & ATAC_VALIDINFO_83) &&
8c97a06b88a7f040b7d72941ca32323bb75cfec7Ada (aidp->ai_ultradma & ATAC_UDMA_SEL_MASK)) ||
8c97a06b88a7f040b7d72941ca32323bb75cfec7Ada (aidp->ai_dworddma & ATAC_MDMA_SEL_MASK))
8c97a06b88a7f040b7d72941ca32323bb75cfec7Ada return (rval);
8c97a06b88a7f040b7d72941ca32323bb75cfec7Ada
c8531848467a8747b65b91ab83c4b57f4c000848yt /* First check Ultra DMA mode if no DMA is selected */
c8531848467a8747b65b91ab83c4b57f4c000848yt if ((aidp->ai_validinfo & ATAC_VALIDINFO_83) &&
c8531848467a8747b65b91ab83c4b57f4c000848yt (aidp->ai_ultradma & ATAC_UDMA_SUP_MASK)) {
c8531848467a8747b65b91ab83c4b57f4c000848yt for (mode = 6; mode >= 0; --mode) {
c8531848467a8747b65b91ab83c4b57f4c000848yt if (aidp->ai_ultradma & (1 << mode))
c8531848467a8747b65b91ab83c4b57f4c000848yt break;
c8531848467a8747b65b91ab83c4b57f4c000848yt }
c8531848467a8747b65b91ab83c4b57f4c000848yt subcmd = ATF_XFRMOD_UDMA;
c8531848467a8747b65b91ab83c4b57f4c000848yt
c8531848467a8747b65b91ab83c4b57f4c000848yt } else if (aidp->ai_dworddma & ATAC_MDMA_SUP_MASK) {
c8531848467a8747b65b91ab83c4b57f4c000848yt /* Then check multi-word DMA mode */
c8531848467a8747b65b91ab83c4b57f4c000848yt for (mode = 2; mode >= 0; --mode) {
c8531848467a8747b65b91ab83c4b57f4c000848yt if (aidp->ai_dworddma & (1 << mode))
c8531848467a8747b65b91ab83c4b57f4c000848yt break;
c8531848467a8747b65b91ab83c4b57f4c000848yt }
c8531848467a8747b65b91ab83c4b57f4c000848yt subcmd = ATF_XFRMOD_MDMA;
c8531848467a8747b65b91ab83c4b57f4c000848yt
c8531848467a8747b65b91ab83c4b57f4c000848yt } else {
c8531848467a8747b65b91ab83c4b57f4c000848yt return (rval);
c8531848467a8747b65b91ab83c4b57f4c000848yt }
c8531848467a8747b65b91ab83c4b57f4c000848yt
c8531848467a8747b65b91ab83c4b57f4c000848yt rval = ata_set_feature(ata_ctlp, ata_drvp, ATSF_SET_XFRMOD,
c8531848467a8747b65b91ab83c4b57f4c000848yt subcmd|mode);
c8531848467a8747b65b91ab83c4b57f4c000848yt
c8531848467a8747b65b91ab83c4b57f4c000848yt return (rval);
c8531848467a8747b65b91ab83c4b57f4c000848yt}
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg/*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * Reset Ultra DMA mode / MWDMA mode
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldbergvoid
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldbergata_reset_dma_mode(ata_drv_t *ata_drvp)
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg{
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg uint8_t subcmd;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg int mode;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg switch (ata_drvp->ad_dma_cap) {
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg case ATA_DMA_ULTRAMODE:
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg subcmd = ATF_XFRMOD_UDMA;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg for (mode = 0; mode <= 6; mode++) {
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg if (ata_drvp->ad_dma_mode & (1 << (mode + 8)))
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg break;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg }
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg break;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg case ATA_DMA_MWORDMODE:
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg subcmd = ATF_XFRMOD_MDMA;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg mode = ((ata_drvp->ad_dma_mode & ATAC_MDMA_2_SEL) ==
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg ATAC_MDMA_2_SEL ? 2 :
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg (ata_drvp->ad_dma_mode & ATAC_MDMA_1_SEL) ==
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg ATAC_MDMA_1_SEL ? 1 : 0);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg break;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg default:
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg return;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg }
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg (void) ata_set_feature(ata_ctlp, ata_drvp, ATSF_SET_XFRMOD,
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg (subcmd | mode));
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg}
fe072f421ec51952432306add7d50852ad1921b2Ada
fe072f421ec51952432306add7d50852ad1921b2Ada/*
fe072f421ec51952432306add7d50852ad1921b2Ada * Check DMA mode is the same with saved info
fe072f421ec51952432306add7d50852ad1921b2Ada * return value: 0 - not same
fe072f421ec51952432306add7d50852ad1921b2Ada * 1 - same
fe072f421ec51952432306add7d50852ad1921b2Ada */
fe072f421ec51952432306add7d50852ad1921b2Adastatic int
fe072f421ec51952432306add7d50852ad1921b2Adaata_check_dma_mode(ata_drv_t *ata_drvp)
fe072f421ec51952432306add7d50852ad1921b2Ada{
fe072f421ec51952432306add7d50852ad1921b2Ada struct ata_id *aidp;
fe072f421ec51952432306add7d50852ad1921b2Ada
fe072f421ec51952432306add7d50852ad1921b2Ada aidp = &ata_drvp->ad_id;
fe072f421ec51952432306add7d50852ad1921b2Ada switch (ata_drvp->ad_dma_cap) {
fe072f421ec51952432306add7d50852ad1921b2Ada case ATA_DMA_ULTRAMODE:
fe072f421ec51952432306add7d50852ad1921b2Ada if ((aidp->ai_validinfo & ATAC_VALIDINFO_83) &&
fe072f421ec51952432306add7d50852ad1921b2Ada (aidp->ai_ultradma & ATAC_UDMA_SEL_MASK) &&
fe072f421ec51952432306add7d50852ad1921b2Ada (aidp->ai_ultradma == ata_drvp->ad_dma_mode))
fe072f421ec51952432306add7d50852ad1921b2Ada break;
fe072f421ec51952432306add7d50852ad1921b2Ada else
fe072f421ec51952432306add7d50852ad1921b2Ada return (0);
fe072f421ec51952432306add7d50852ad1921b2Ada case ATA_DMA_MWORDMODE:
fe072f421ec51952432306add7d50852ad1921b2Ada if ((aidp->ai_dworddma & ATAC_MDMA_SEL_MASK) &&
fe072f421ec51952432306add7d50852ad1921b2Ada (aidp->ai_dworddma == ata_drvp->ad_dma_mode))
fe072f421ec51952432306add7d50852ad1921b2Ada break;
fe072f421ec51952432306add7d50852ad1921b2Ada else
fe072f421ec51952432306add7d50852ad1921b2Ada return (0);
fe072f421ec51952432306add7d50852ad1921b2Ada default:
fe072f421ec51952432306add7d50852ad1921b2Ada return (0);
fe072f421ec51952432306add7d50852ad1921b2Ada }
fe072f421ec51952432306add7d50852ad1921b2Ada return (1);
fe072f421ec51952432306add7d50852ad1921b2Ada}