xref: /onnv-gate/usr/src/uts/common/io/pcmcia/pcide.c (revision 7656:2621e50fdf4a)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7656SSherry.Moore@Sun.COM  * Common Development and Distribution License (the "License").
6*7656SSherry.Moore@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*7656SSherry.Moore@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate 
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * ATA  disk driver
300Sstevel@tonic-gate  *
310Sstevel@tonic-gate  * Handles the standard PCMCIA ATA interface
320Sstevel@tonic-gate  *
330Sstevel@tonic-gate  */
340Sstevel@tonic-gate #include <sys/errno.h>
350Sstevel@tonic-gate #include <sys/param.h>
360Sstevel@tonic-gate #include <sys/systm.h>
370Sstevel@tonic-gate #include <sys/user.h>
380Sstevel@tonic-gate #include <sys/buf.h>
390Sstevel@tonic-gate #include <sys/ioctl.h>
400Sstevel@tonic-gate #include <sys/file.h>
410Sstevel@tonic-gate #include <sys/uio.h>
420Sstevel@tonic-gate #include <sys/fcntl.h>
430Sstevel@tonic-gate #include <sys/cmn_err.h>
440Sstevel@tonic-gate #include <sys/kmem.h>
450Sstevel@tonic-gate #include <sys/sysmacros.h>
460Sstevel@tonic-gate #include <sys/stat.h>
470Sstevel@tonic-gate #include <sys/scsi/scsi.h>
480Sstevel@tonic-gate 
490Sstevel@tonic-gate #include <sys/fdio.h>
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #include <sys/errno.h>
520Sstevel@tonic-gate #include <sys/open.h>
530Sstevel@tonic-gate #include <sys/varargs.h>
540Sstevel@tonic-gate #include <sys/fs/pc_label.h>
550Sstevel@tonic-gate 
560Sstevel@tonic-gate #include <sys/hdio.h>
570Sstevel@tonic-gate #include <sys/dkio.h>
580Sstevel@tonic-gate #include <sys/dktp/dadkio.h>
590Sstevel@tonic-gate 
600Sstevel@tonic-gate #include <sys/dklabel.h>
610Sstevel@tonic-gate 
620Sstevel@tonic-gate #include <sys/vtoc.h>
630Sstevel@tonic-gate 
640Sstevel@tonic-gate #include <sys/types.h>
650Sstevel@tonic-gate #include <sys/conf.h>
660Sstevel@tonic-gate #include <sys/dditypes.h>
670Sstevel@tonic-gate #include <sys/ddi.h>
680Sstevel@tonic-gate #include <sys/sunddi.h>
690Sstevel@tonic-gate #include <sys/dktp/cm.h>
700Sstevel@tonic-gate 
710Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
720Sstevel@tonic-gate 
730Sstevel@tonic-gate #include <sys/fs/pc_label.h>
740Sstevel@tonic-gate 
750Sstevel@tonic-gate #include <sys/pctypes.h>
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 
780Sstevel@tonic-gate /*
790Sstevel@tonic-gate  * PCMCIA and DDI related header files
800Sstevel@tonic-gate  */
810Sstevel@tonic-gate #include <sys/pccard.h>
820Sstevel@tonic-gate 
830Sstevel@tonic-gate #include <sys/pcmcia/pcata.h>
840Sstevel@tonic-gate 
850Sstevel@tonic-gate int	pcata_debug = 0;
860Sstevel@tonic-gate 
870Sstevel@tonic-gate static int pcata_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
880Sstevel@tonic-gate static int pcata_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
890Sstevel@tonic-gate static int pcata_att1(dev_info_t *dip, ata_soft_t *softp);
900Sstevel@tonic-gate static int pcata_go(ata_unit_t *unitp);
910Sstevel@tonic-gate static int pcata_wait(uint32_t port, ushort_t onbits, ushort_t offbits,
920Sstevel@tonic-gate 	ata_soft_t *softp);
930Sstevel@tonic-gate static int pcata_wait1(uint32_t port, ushort_t onbits, ushort_t offbits,
940Sstevel@tonic-gate 	int interval, ata_soft_t *softp);
950Sstevel@tonic-gate static void pcata_wait_complete(ata_soft_t *softp);
960Sstevel@tonic-gate static uchar_t pcata_drive_type(ata_soft_t *softp, ushort_t *secbuf);
970Sstevel@tonic-gate static int pcata_setpar(int drive, int heads, int sectors, ata_soft_t *softp);
980Sstevel@tonic-gate static int pcata_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk);
990Sstevel@tonic-gate static int pcata_print(dev_t dev, char *str);
1000Sstevel@tonic-gate static int pcata_rdrw(dev_t dev, struct uio *uio, int flag);
1010Sstevel@tonic-gate static int pcata_read(dev_t dev, struct uio *uio, cred_t *cred_p);
1020Sstevel@tonic-gate static int pcata_write(dev_t dev, struct uio *uio, cred_t *cred_p);
1030Sstevel@tonic-gate #ifdef  ATA_DEBUG
1040Sstevel@tonic-gate static void pcata_print_sttflag(int svalue);
1050Sstevel@tonic-gate #endif
1060Sstevel@tonic-gate static void pcata_clear_queues(ata_unit_t *unitp);
1070Sstevel@tonic-gate static void pcata_nack_packet(struct ata_cmpkt *pktp);
1080Sstevel@tonic-gate static void pcata_iosetup(ata_unit_t *unitp, struct ata_cmpkt *pktp);
1090Sstevel@tonic-gate static int pcata_send_data(ata_unit_t *unitp, int count);
1100Sstevel@tonic-gate static int pcata_get_data(ata_unit_t *unitp, int count);
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate struct cb_ops pcata_cb_ops = {
1130Sstevel@tonic-gate 		pcata_open,		/* driver open routine		*/
1140Sstevel@tonic-gate 		pcata_close,		/* driver close routine		*/
1150Sstevel@tonic-gate 		pcata_strategy,		/* driver strategy routine	*/
1160Sstevel@tonic-gate 		pcata_print,		/* driver print routine		*/
1170Sstevel@tonic-gate 		pcata_dump,		/* driver dump routine		*/
1180Sstevel@tonic-gate 		pcata_read,		/* driver read routine		*/
1190Sstevel@tonic-gate 		pcata_write,		/* driver write routine		*/
1200Sstevel@tonic-gate 		pcata_ioctl,		/* driver ioctl routine		*/
1210Sstevel@tonic-gate 		nodev,			/* driver devmap routine	*/
1220Sstevel@tonic-gate 		nodev,			/* driver mmap routine		*/
1230Sstevel@tonic-gate 		nodev,			/* driver segmap routine	*/
1240Sstevel@tonic-gate 		nochpoll,		/* driver chpoll routine	*/
1250Sstevel@tonic-gate 		pcata_prop_op,		/* driver prop_op routine	*/
1260Sstevel@tonic-gate 		0,			/* driver cb_str - STREAMS only	*/
1270Sstevel@tonic-gate 		D_NEW | D_MTSAFE,	/* driver compatibility flag	*/
1280Sstevel@tonic-gate 	};
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate static struct dev_ops ata_ops = {
1310Sstevel@tonic-gate 		DEVO_REV,		/* devo_rev, */
1320Sstevel@tonic-gate 		0,			/* refcnt  */
1330Sstevel@tonic-gate 		pcata_getinfo,		/* info */
1340Sstevel@tonic-gate 		nulldev,		/* identify */
1350Sstevel@tonic-gate 		nulldev,		/* probe */
1360Sstevel@tonic-gate 		pcata_attach,		/* attach */
1370Sstevel@tonic-gate 		pcata_detach,		/* detach */
1380Sstevel@tonic-gate 		nulldev,		/* reset */
1390Sstevel@tonic-gate 		&pcata_cb_ops,		/* driver operations */
140*7656SSherry.Moore@Sun.COM 		NULL,			/* bus operations */
141*7656SSherry.Moore@Sun.COM 		NULL,			/* power */
142*7656SSherry.Moore@Sun.COM 		ddi_quiesce_not_needed,		/* quiesce */
1430Sstevel@tonic-gate 	};
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate void	*pcata_soft = NULL;
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate #include <sys/modctl.h>
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate extern  struct mod_ops  mod_driverops;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate static struct modldrv modldrv = {
1550Sstevel@tonic-gate 		&mod_driverops, /* Type of module. This one is a driver */
156*7656SSherry.Moore@Sun.COM 		"PCMCIA ATA disk controller",
1570Sstevel@tonic-gate 		&ata_ops, /* driver ops */
1580Sstevel@tonic-gate 	};
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate static struct modlinkage modlinkage = {
1610Sstevel@tonic-gate 		MODREV_1, (void *)&modldrv, NULL
1620Sstevel@tonic-gate 	};
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate int
_init(void)1650Sstevel@tonic-gate _init(void)
1660Sstevel@tonic-gate {
1670Sstevel@tonic-gate 	int	status;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	status = mod_install(&modlinkage);
1700Sstevel@tonic-gate 	if (status)
1710Sstevel@tonic-gate 		return (status);
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	status = ddi_soft_state_init(&pcata_soft, sizeof (ata_soft_t), 1);
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	return (status);
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate int
_fini(void)1800Sstevel@tonic-gate _fini(void)
1810Sstevel@tonic-gate {
1820Sstevel@tonic-gate 	int	status;
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	status = mod_remove(&modlinkage);
1850Sstevel@tonic-gate 	if (!status)
1860Sstevel@tonic-gate 		ddi_soft_state_fini(&pcata_soft);
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	return (status);
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1930Sstevel@tonic-gate _info(struct modinfo *modinfop)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate static int
pcata_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1990Sstevel@tonic-gate pcata_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate 	int		instance = ddi_get_instance(dip);
2020Sstevel@tonic-gate 	ata_soft_t	*softp;
2030Sstevel@tonic-gate 	int		ret;
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	/* resume from a checkpoint */
2060Sstevel@tonic-gate 	if (cmd == DDI_RESUME)
207*7656SSherry.Moore@Sun.COM 		return (DDI_SUCCESS);
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	if (cmd != DDI_ATTACH) {
2100Sstevel@tonic-gate #ifdef  ATA_DEBUG
2110Sstevel@tonic-gate 		cmn_err(CE_CONT, "_attach returning FAILURE\n");
2120Sstevel@tonic-gate #endif
2130Sstevel@tonic-gate 		return (DDI_FAILURE);
2140Sstevel@tonic-gate 	}
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 	/* Allocate soft state associated with this instance. */
2170Sstevel@tonic-gate 	ret = ddi_soft_state_zalloc(pcata_soft, ddi_get_instance(dip));
2180Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
2190Sstevel@tonic-gate #ifdef  ATA_DEBUG
2200Sstevel@tonic-gate 		cmn_err(CE_CONT, "_attach: Unable to alloc state\n");
2210Sstevel@tonic-gate #endif
2220Sstevel@tonic-gate 		return (DDI_FAILURE);
2230Sstevel@tonic-gate 	}
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	softp = ddi_get_soft_state(pcata_soft, instance);
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate #ifdef  ATA_DEBUG
2280Sstevel@tonic-gate 	if (pcata_debug & DINIT)
2290Sstevel@tonic-gate 		cmn_err(CE_CONT, "_attach softp=%p\n", (void *)softp);
2300Sstevel@tonic-gate #endif
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	softp->dip		= dip;
2330Sstevel@tonic-gate 	softp->instance		= instance;
2340Sstevel@tonic-gate 	softp->ab_dip		= dip;
2350Sstevel@tonic-gate 	softp->crashbuf		= getrbuf(KM_SLEEP);
2360Sstevel@tonic-gate 	softp->flags		= 0;
2370Sstevel@tonic-gate 	softp->card_state	= 0;
2380Sstevel@tonic-gate 	softp->intr_pending	= 0;
2390Sstevel@tonic-gate 	softp->softint_pending	= 0;
2400Sstevel@tonic-gate 	softp->write_in_progress = 0;
2410Sstevel@tonic-gate 	softp->blk_open		= 0;
2420Sstevel@tonic-gate 	softp->chr_open		= 0;
2430Sstevel@tonic-gate 	softp->ejected_while_mounted = 0;
2440Sstevel@tonic-gate 	bzero(softp->lyr_open, sizeof (softp->lyr_open[NUM_PARTS]));
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	/*
2470Sstevel@tonic-gate 	 * Initialize to 0 until it is incremented in pcram_check_media
2480Sstevel@tonic-gate 	 */
2490Sstevel@tonic-gate 	softp->checkmedia_flag =  0;
2500Sstevel@tonic-gate 	softp->ejected_media_flag =  0;
2510Sstevel@tonic-gate 	softp->media_state = DKIO_NONE;
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	/*
2540Sstevel@tonic-gate 	 * if attach fails, Solaris won't call detach
2550Sstevel@tonic-gate 	 * so we call detach here to release all flagged resources
2560Sstevel@tonic-gate 	 */
2570Sstevel@tonic-gate 	ret = pcata_att1(dip, softp);
2580Sstevel@tonic-gate 	if (ret == DDI_FAILURE) {
2590Sstevel@tonic-gate 		(void) pcata_detach(dip, DDI_DETACH);
2600Sstevel@tonic-gate 		return (DDI_FAILURE);
2610Sstevel@tonic-gate 	}
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	return (DDI_SUCCESS);
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate static int
pcata_att1(dev_info_t * dip,ata_soft_t * softp)2670Sstevel@tonic-gate pcata_att1(dev_info_t *dip, ata_soft_t *softp)
2680Sstevel@tonic-gate {
2690Sstevel@tonic-gate 	int		ret;
2700Sstevel@tonic-gate 	client_reg_t	client_reg;
2710Sstevel@tonic-gate 	sockmask_t	sockmask;
2720Sstevel@tonic-gate 	map_log_socket_t map_log_socket;
2730Sstevel@tonic-gate 	cs_ddi_info_t	cs_ddi_info;
2740Sstevel@tonic-gate 	get_status_t	get_status;
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	/*
2780Sstevel@tonic-gate 	 * create ata_mutex
2790Sstevel@tonic-gate 	 */
2800Sstevel@tonic-gate 	ret = ddi_get_soft_iblock_cookie(dip, DDI_SOFTINT_MED,
281*7656SSherry.Moore@Sun.COM 	    &softp->soft_blk_cookie);
2820Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
2830Sstevel@tonic-gate #ifdef ATA_DEBUG
2840Sstevel@tonic-gate 		cmn_err(CE_CONT, "_attach: unable to get iblock cookie\n");
2850Sstevel@tonic-gate #endif
2860Sstevel@tonic-gate 		return (ret);
2870Sstevel@tonic-gate 	}
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	/*
2910Sstevel@tonic-gate 	 * Setup the mutexii and condition variables.
2920Sstevel@tonic-gate 	 * Initialize the mutex that protects the ATA registers.
2930Sstevel@tonic-gate 	 */
2940Sstevel@tonic-gate 	mutex_init(&softp->ata_mutex, NULL, MUTEX_DRIVER,
295*7656SSherry.Moore@Sun.COM 	    (void *)(softp->soft_blk_cookie));
2960Sstevel@tonic-gate 	mutex_init(&softp->label_mutex, NULL, MUTEX_DRIVER, NULL);
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	cv_init(&softp->readywait_cv, NULL, CV_DRIVER, NULL);
2990Sstevel@tonic-gate 	/* for DKIOCSTATE ioctl()  */
3000Sstevel@tonic-gate 	cv_init(&softp->condvar_mediastate, NULL, CV_DRIVER, NULL);
3010Sstevel@tonic-gate 	softp->flags |= PCATA_DIDLOCKS;
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	/*
3050Sstevel@tonic-gate 	 * link in soft interrupt
3060Sstevel@tonic-gate 	 */
3070Sstevel@tonic-gate 	ret = ddi_add_softintr(dip, DDI_SOFTINT_MED, &softp->softint_id,
308*7656SSherry.Moore@Sun.COM 	    NULL, NULL, pcata_intr, (caddr_t)softp);
3090Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
3100Sstevel@tonic-gate #ifdef ATA_DEBUG
3110Sstevel@tonic-gate 		cmn_err(CE_CONT, "_attach: unable to get soft interrupt\n");
3120Sstevel@tonic-gate #endif
3130Sstevel@tonic-gate 		return (DDI_FAILURE);
3140Sstevel@tonic-gate 	}
3150Sstevel@tonic-gate 	softp->flags |= PCATA_SOFTINTROK;
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	/*
3190Sstevel@tonic-gate 	 * Register with Card Services
3200Sstevel@tonic-gate 	 */
3210Sstevel@tonic-gate 	client_reg.Attributes =
322*7656SSherry.Moore@Sun.COM 	    INFO_IO_CLIENT | INFO_CARD_SHARE | INFO_CARD_EXCL;
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	client_reg.EventMask =
325*7656SSherry.Moore@Sun.COM 	    CS_EVENT_CARD_INSERTION |
326*7656SSherry.Moore@Sun.COM 	    CS_EVENT_CARD_REMOVAL |
327*7656SSherry.Moore@Sun.COM 	    CS_EVENT_CARD_REMOVAL_LOWP |
328*7656SSherry.Moore@Sun.COM 	    CS_EVENT_PM_RESUME |
329*7656SSherry.Moore@Sun.COM 	    CS_EVENT_CLIENT_INFO |
330*7656SSherry.Moore@Sun.COM 	    CS_EVENT_PM_SUSPEND |
331*7656SSherry.Moore@Sun.COM 	    CS_EVENT_REGISTRATION_COMPLETE;
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	client_reg.event_handler = (csfunction_t *)pcata_event;
3340Sstevel@tonic-gate 	client_reg.event_callback_args.client_data = softp;
3350Sstevel@tonic-gate 	client_reg.Version = _VERSION(2, 1);
3360Sstevel@tonic-gate 	client_reg.dip = dip;
3370Sstevel@tonic-gate 	(void) strcpy(client_reg.driver_name, pcata_name);
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	ret = csx_RegisterClient(&softp->client_handle, &client_reg);
3400Sstevel@tonic-gate 	if (ret != CS_SUCCESS) {
3410Sstevel@tonic-gate #ifdef  ATA_DEBUG
3420Sstevel@tonic-gate 		cmn_err(CE_CONT, "_attach RegisterClient failed %s\n",
343*7656SSherry.Moore@Sun.COM 		    pcata_CS_etext(ret));
3440Sstevel@tonic-gate #endif
3450Sstevel@tonic-gate 		return (DDI_FAILURE);
3460Sstevel@tonic-gate 	}
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 	mutex_init(&softp->event_hilock, NULL, MUTEX_DRIVER,
349*7656SSherry.Moore@Sun.COM 	    *(client_reg.iblk_cookie));
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 	softp->flags |= PCATA_REGCLIENT;
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 	/*
3550Sstevel@tonic-gate 	 * Get logical socket number and store in softp struct
3560Sstevel@tonic-gate 	 */
3570Sstevel@tonic-gate 	ret = csx_MapLogSocket(softp->client_handle, &map_log_socket);
3580Sstevel@tonic-gate 	if (ret != CS_SUCCESS) {
3590Sstevel@tonic-gate #ifdef  ATA_DEBUG
3600Sstevel@tonic-gate 		cmn_err(CE_CONT, "_attach: MapLogSocket failed %s\n",
361*7656SSherry.Moore@Sun.COM 		    pcata_CS_etext(ret));
3620Sstevel@tonic-gate #endif
3630Sstevel@tonic-gate 		return (DDI_FAILURE);
3640Sstevel@tonic-gate 	}
3650Sstevel@tonic-gate 	softp->sn = map_log_socket.PhySocket;
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	/*
3690Sstevel@tonic-gate 	 *
3700Sstevel@tonic-gate 	 */
3710Sstevel@tonic-gate 	cs_ddi_info.Socket	= softp->sn;
3720Sstevel@tonic-gate 	cs_ddi_info.driver_name = pcata_name;
3730Sstevel@tonic-gate 	cs_ddi_info.dip		= dip;
3740Sstevel@tonic-gate 	cs_ddi_info.instance	= softp->instance;
3750Sstevel@tonic-gate 	if ((ret = csx_CS_DDI_Info(&cs_ddi_info)) != CS_SUCCESS) {
3760Sstevel@tonic-gate #ifdef  ATA_DEBUG
3770Sstevel@tonic-gate 		cmn_err(CE_CONT, "_attach: socket %d CS_DDI_Info failed %s\n",
378*7656SSherry.Moore@Sun.COM 		    softp->sn, pcata_CS_etext(ret));
3790Sstevel@tonic-gate #endif
3800Sstevel@tonic-gate 		return (DDI_FAILURE);
3810Sstevel@tonic-gate 	}
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	/*
3840Sstevel@tonic-gate 	 * After the RequestSocketMask call, we start receiving events
3850Sstevel@tonic-gate 	 */
3860Sstevel@tonic-gate 	sockmask.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL;
3870Sstevel@tonic-gate 	ret = csx_RequestSocketMask(softp->client_handle, &sockmask);
3880Sstevel@tonic-gate 	if (ret != CS_SUCCESS) {
3890Sstevel@tonic-gate #ifdef  ATA_DEBUG
3900Sstevel@tonic-gate 		cmn_err(CE_CONT, "_attach: RequestSocketMask failed %s\n",
391*7656SSherry.Moore@Sun.COM 		    pcata_CS_etext(ret));
3920Sstevel@tonic-gate #endif
3930Sstevel@tonic-gate 		return (DDI_FAILURE);
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate 	softp->flags |= PCATA_REQSOCKMASK;
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	/*
3980Sstevel@tonic-gate 	 * We may not get the CARD_READY event
3990Sstevel@tonic-gate 	 * until after we leave this function.
4000Sstevel@tonic-gate 	 */
4010Sstevel@tonic-gate 	mutex_enter(&softp->event_hilock);
4020Sstevel@tonic-gate 	softp->card_state |= PCATA_READY_WAIT;
4030Sstevel@tonic-gate 	mutex_exit(&softp->event_hilock);
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	(void) csx_GetStatus(softp->client_handle, &get_status);
4060Sstevel@tonic-gate 	if (get_status.raw_CardState & CS_STATUS_CARD_INSERTED) {
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 		/* wait for drive to be initialized */
4090Sstevel@tonic-gate 		(void) pcata_readywait(softp);
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 		if ((softp->card_state & PCATA_CARD_INSERTED) == 0 ||
412*7656SSherry.Moore@Sun.COM 		    (softp->flags & PCATA_READY) == 0) {
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 			mutex_enter(&softp->ata_mutex);
4150Sstevel@tonic-gate 			mutex_enter(&softp->event_hilock);
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 			softp->card_state &= ~PCATA_READY_WAIT;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 			mutex_exit(&softp->event_hilock);
4200Sstevel@tonic-gate 			mutex_exit(&softp->ata_mutex);
4210Sstevel@tonic-gate 		}
4220Sstevel@tonic-gate 	}
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 	/*
4250Sstevel@tonic-gate 	 * Wait for minor node creation before returning
4260Sstevel@tonic-gate 	 */
4270Sstevel@tonic-gate 	pcata_minor_wait(softp);
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	/*
4300Sstevel@tonic-gate 	 * print banner to announce device
4310Sstevel@tonic-gate 	 */
4320Sstevel@tonic-gate 	ddi_report_dev(dip);
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate 	return (DDI_SUCCESS);
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate static int
pcata_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)4380Sstevel@tonic-gate pcata_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
4390Sstevel@tonic-gate {
4400Sstevel@tonic-gate 	int	instance = ddi_get_instance(devi);
4410Sstevel@tonic-gate 	ata_soft_t *softp;
4420Sstevel@tonic-gate 	int	ret;
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	if (cmd == DDI_SUSPEND)
445*7656SSherry.Moore@Sun.COM 		return (DDI_SUCCESS);
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate 	if (cmd != DDI_DETACH)
4480Sstevel@tonic-gate 		return (DDI_FAILURE);
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	softp = ddi_get_soft_state(pcata_soft, instance);
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 	/*
4540Sstevel@tonic-gate 	 * Call the card_removal routine to do any final card cleanup
4550Sstevel@tonic-gate 	 */
4560Sstevel@tonic-gate 	if (CARD_PRESENT_VALID(softp)) {
4570Sstevel@tonic-gate 		(void) pcata_card_removal(softp, CS_EVENT_PRI_LOW);
4580Sstevel@tonic-gate 	}
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 	/*
4620Sstevel@tonic-gate 	 * Release our socket mask - note that we can't do much
4630Sstevel@tonic-gate 	 * if we fail these calls other than to note that
4640Sstevel@tonic-gate 	 * the system will probably panic shortly.  Perhaps
4650Sstevel@tonic-gate 	 * we should fail the detach in the case where these
4660Sstevel@tonic-gate 	 * CS calls fail?
4670Sstevel@tonic-gate 	 */
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 	if (softp->flags & PCATA_REQSOCKMASK) {
4700Sstevel@tonic-gate 		release_socket_mask_t rsm;
4710Sstevel@tonic-gate 		ret = csx_ReleaseSocketMask(softp->client_handle, &rsm);
4720Sstevel@tonic-gate 		if (ret != CS_SUCCESS) {
4730Sstevel@tonic-gate #ifdef ATA_DEBUG
4740Sstevel@tonic-gate 			cmn_err(CE_CONT, "_detach "
475*7656SSherry.Moore@Sun.COM 			    "ReleaseSocketMask failed %s\n",
476*7656SSherry.Moore@Sun.COM 			    pcata_CS_etext(ret));
4770Sstevel@tonic-gate #endif
4780Sstevel@tonic-gate 		}
4790Sstevel@tonic-gate 	}
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	/*
4830Sstevel@tonic-gate 	 * Deregister with Card Services - we will stop getting
4840Sstevel@tonic-gate 	 * events at this point.
4850Sstevel@tonic-gate 	 */
4860Sstevel@tonic-gate 	if (softp->flags & PCATA_REGCLIENT) {
4870Sstevel@tonic-gate 		ret = csx_DeregisterClient(softp->client_handle);
4880Sstevel@tonic-gate 		if (ret != CS_SUCCESS) {
4890Sstevel@tonic-gate #ifdef ATA_DEBUG
4900Sstevel@tonic-gate 			cmn_err(CE_CONT, "_detach: "
491*7656SSherry.Moore@Sun.COM 			    "DeregisterClient failed %s\n",
492*7656SSherry.Moore@Sun.COM 			    pcata_CS_etext(ret));
4930Sstevel@tonic-gate #endif
4940Sstevel@tonic-gate 			return (DDI_FAILURE);
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 		}
4970Sstevel@tonic-gate 		softp->flags &= ~PCATA_REGCLIENT;
4980Sstevel@tonic-gate 	}
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	/* unregister the softintrrupt handler */
5020Sstevel@tonic-gate 	if (softp->flags & PCATA_SOFTINTROK) {
5030Sstevel@tonic-gate 		ddi_remove_softintr(softp->softint_id);
5040Sstevel@tonic-gate 		softp->flags &= ~PCATA_SOFTINTROK;
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 	}
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	if (softp->flags & PCATA_DIDLOCKS) {
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 		/*
5110Sstevel@tonic-gate 		 * XXX/lcl make sure no threads are blocked
5120Sstevel@tonic-gate 		 */
5130Sstevel@tonic-gate 		mutex_destroy(&softp->ata_mutex);
5140Sstevel@tonic-gate 		mutex_destroy(&softp->event_hilock);
5150Sstevel@tonic-gate 		mutex_destroy(&softp->label_mutex);
5160Sstevel@tonic-gate 		cv_destroy(&softp->readywait_cv);
5170Sstevel@tonic-gate 		/* for DKIOCSTATE ioctl()  */
5180Sstevel@tonic-gate 		cv_destroy(&softp->condvar_mediastate);
5190Sstevel@tonic-gate 		softp->flags &= ~PCATA_DIDLOCKS;
5200Sstevel@tonic-gate 	}
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	/* Free various structures and memory here. */
5230Sstevel@tonic-gate 	if (softp && softp->crashbuf)
5240Sstevel@tonic-gate 		freerbuf(softp->crashbuf);
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 	/* Free the soft state structure here */
5270Sstevel@tonic-gate 	ddi_soft_state_free(pcata_soft, instance);
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate #ifdef ATA_DEBUG
5300Sstevel@tonic-gate 	if (pcata_debug & DPCM)
5310Sstevel@tonic-gate 		cmn_err(CE_NOTE, "successful detach\n");
5320Sstevel@tonic-gate #endif
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	return (DDI_SUCCESS);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate /*
5390Sstevel@tonic-gate  *	Common controller object interface
5400Sstevel@tonic-gate  */
5410Sstevel@tonic-gate /*
5420Sstevel@tonic-gate  * initiate a new I/O request
5430Sstevel@tonic-gate  * either start it or add it to the request queue
5440Sstevel@tonic-gate  */
5450Sstevel@tonic-gate int
pcata_start(ata_unit_t * unitp,buf_t * bp,int blkno)5460Sstevel@tonic-gate pcata_start(ata_unit_t *unitp, buf_t *bp, int blkno)
5470Sstevel@tonic-gate {
5480Sstevel@tonic-gate 	ata_soft_t	*softp = unitp->a_blkp;
5490Sstevel@tonic-gate 	struct ata_cmpkt *pktp;
5500Sstevel@tonic-gate 	int		ret;
5510Sstevel@tonic-gate 	int		kf = 0;
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	ASSERT(mutex_owned(&softp->ata_mutex));
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate #ifdef ATA_DEBUG
5560Sstevel@tonic-gate 	if (pcata_debug & DENT) {
5570Sstevel@tonic-gate 		cmn_err(CE_CONT, "_start unitp=%p, bp=%p bp->b_private=%p\n",
558*7656SSherry.Moore@Sun.COM 		    (void *)unitp,
559*7656SSherry.Moore@Sun.COM 		    (void *)bp,
560*7656SSherry.Moore@Sun.COM 		    bp->b_private);
5610Sstevel@tonic-gate 	}
5620Sstevel@tonic-gate #endif
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 	if (!CARD_PRESENT_VALID(softp))
5650Sstevel@tonic-gate 		return (CTL_SEND_FAILURE);
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate 	/* XXX/lcl why is this different from CARD_PRESENT_VALID */
5680Sstevel@tonic-gate 	if (softp->ab_status_flag & ATA_OFFLINE) {
5690Sstevel@tonic-gate 		return (CTL_SEND_FAILURE);
5700Sstevel@tonic-gate 	}
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	pktp = (struct ata_cmpkt *)kmem_zalloc(sizeof (*pktp),  kf);
5730Sstevel@tonic-gate 	if (!pktp) {
5740Sstevel@tonic-gate 		cmn_err(CE_NOTE, "_start kmem_zalloc failed\n");
5750Sstevel@tonic-gate 		return (CTL_SEND_FAILURE);
5760Sstevel@tonic-gate 	}
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate #ifdef ATA_DEBUG
5790Sstevel@tonic-gate 	if (pcata_debug & DENT)
5800Sstevel@tonic-gate 		cmn_err(CE_CONT, "_start pktp=%p\n", (void *)pktp);
5810Sstevel@tonic-gate #endif
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 	if ((bp->b_flags & B_PAGEIO) || (bp->b_flags & B_PHYS))
5840Sstevel@tonic-gate 		bp_mapin(bp);
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 	pktp->ac_bytes_per_block = unitp->au_bytes_per_block;
5870Sstevel@tonic-gate 	pktp->ac_start_v_addr	= bp->b_un.b_addr;	/* xfer address */
5880Sstevel@tonic-gate 	pktp->cp_bytexfer	= bp->b_bcount;
5890Sstevel@tonic-gate 	pktp->cp_bp		= bp;
5900Sstevel@tonic-gate 	pktp->cp_ctl_private	= unitp;
5910Sstevel@tonic-gate 	pktp->cp_srtsec		= blkno;
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 	if (bp->b_flags & B_READ) {
5940Sstevel@tonic-gate 		pktp->ac_direction	= AT_IN;
5950Sstevel@tonic-gate 		pktp->ac_cdb		= DCMD_READ;
5960Sstevel@tonic-gate 	} else {
5970Sstevel@tonic-gate 		pktp->ac_direction	= AT_OUT;
5980Sstevel@tonic-gate 		pktp->ac_cdb		= DCMD_WRITE;
5990Sstevel@tonic-gate 	}
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 	/*
6020Sstevel@tonic-gate 	 * b_private is set to 0xBEE by pcata_buf_setup
6030Sstevel@tonic-gate 	 * which is called by an ioctl DIOCTL_RWCMD with a subcommand
6040Sstevel@tonic-gate 	 * of either DADKIO_RWCMD_READ or DADKIO_RWCMD_WRITE
6050Sstevel@tonic-gate 	 *
6060Sstevel@tonic-gate 	 * these commands are used to do I/O through the IOCTL interface
6070Sstevel@tonic-gate 	 *
6080Sstevel@tonic-gate 	 * b_back contains a pointer to the ioctl packet struct (dadkio_rwcmd)
6090Sstevel@tonic-gate 	 */
6100Sstevel@tonic-gate 	if (bp->b_private == (void *)0xBEE)
6110Sstevel@tonic-gate 		pktp->cp_passthru = bp->b_back;
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate #ifdef ATA_DEBUG
6140Sstevel@tonic-gate 	if (pcata_debug & DIO) {
6150Sstevel@tonic-gate 		cmn_err(CE_CONT, "passthru command seen: 0x%p\n",
616*7656SSherry.Moore@Sun.COM 		    pktp->cp_passthru);
6170Sstevel@tonic-gate 	}
6180Sstevel@tonic-gate #endif
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 	pcata_iosetup(unitp, pktp);	/* fill a packet */
6210Sstevel@tonic-gate 	pktp->pkt_forw = 0;
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate #ifdef ATA_DEBUG
6240Sstevel@tonic-gate 	if (pcata_debug & DIO) {
6250Sstevel@tonic-gate 		cmn_err(CE_CONT, "_start: active: %c  head: %c\n",
626*7656SSherry.Moore@Sun.COM 		    (softp->ab_active == NULL ? 'N' : 'Y'),
627*7656SSherry.Moore@Sun.COM 		    (softp->ab_head == NULL ? 'N' : 'Y'));
6280Sstevel@tonic-gate 	}
6290Sstevel@tonic-gate #endif
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	if (softp->ab_active == NULL) {
6320Sstevel@tonic-gate 		/*
6330Sstevel@tonic-gate 		 * The controller is idle.
6340Sstevel@tonic-gate 		 * Put the packet in ab_active....
6350Sstevel@tonic-gate 		 */
6360Sstevel@tonic-gate 		softp->ab_active = pktp;
6370Sstevel@tonic-gate 		/*
6380Sstevel@tonic-gate 		 * ... and start it off
6390Sstevel@tonic-gate 		 */
6400Sstevel@tonic-gate 		ret = PCATA_GO_RETRY;
6410Sstevel@tonic-gate 		while (ret ==  PCATA_GO_RETRY) {
6420Sstevel@tonic-gate 			ret = pcata_go(unitp);
6430Sstevel@tonic-gate 		}
6440Sstevel@tonic-gate 		if (ret == DDI_FAILURE) {
6450Sstevel@tonic-gate 			cmn_err(CE_NOTE, "start_cmd failure \n");
6460Sstevel@tonic-gate 			softp->ab_active = NULL;
6470Sstevel@tonic-gate 			return (CTL_SEND_FAILURE);
6480Sstevel@tonic-gate 		}
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 	} else {
6510Sstevel@tonic-gate 		/*
6520Sstevel@tonic-gate 		 * the controller is busy now so put the packet
6530Sstevel@tonic-gate 		 * on ab_head or ab_last.
6540Sstevel@tonic-gate 		 */
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 		if (softp->ab_head == NULL)
6570Sstevel@tonic-gate 			softp->ab_head = pktp;
6580Sstevel@tonic-gate 		else
6590Sstevel@tonic-gate 			softp->ab_last->pkt_forw = pktp;
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 		softp->ab_last = pktp;
6620Sstevel@tonic-gate 	}
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 	return (CTL_SEND_SUCCESS);
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate /*
6690Sstevel@tonic-gate  * initiate I/O for packet linked on ab_active
6700Sstevel@tonic-gate  */
6710Sstevel@tonic-gate static int
pcata_go(ata_unit_t * unitp)6720Sstevel@tonic-gate pcata_go(ata_unit_t *unitp)
6730Sstevel@tonic-gate {
6740Sstevel@tonic-gate 	ata_soft_t	*softp = unitp->a_blkp;
6750Sstevel@tonic-gate 	struct ata_cmpkt *pktp = softp->ab_active;
6760Sstevel@tonic-gate 	uint32_t	nbytes;
6770Sstevel@tonic-gate 	uint32_t	start_sec;
6780Sstevel@tonic-gate 	uint32_t	cyl;
6790Sstevel@tonic-gate 	uint32_t	resid;
6800Sstevel@tonic-gate 	uchar_t		head;
6810Sstevel@tonic-gate 	uchar_t		drvheads;
6820Sstevel@tonic-gate 	uchar_t		drvsectors;
6830Sstevel@tonic-gate 
6840Sstevel@tonic-gate 	uchar_t		ac_devctl;
6850Sstevel@tonic-gate 	uchar_t		ac_sec;
6860Sstevel@tonic-gate 	uchar_t		ac_count;
6870Sstevel@tonic-gate 	uchar_t		ac_lwcyl;
6880Sstevel@tonic-gate 	uchar_t		ac_hicyl;
6890Sstevel@tonic-gate 	uchar_t		ac_hd;
6900Sstevel@tonic-gate 
6910Sstevel@tonic-gate 	ASSERT(mutex_owned(&softp->ata_mutex));
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	if (pktp == NULL)
6940Sstevel@tonic-gate 		return (DDI_SUCCESS);
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	if (!CARD_PRESENT_VALID(softp)) {
6970Sstevel@tonic-gate 		pktp->ac_scb	= DERR_ABORT;
6980Sstevel@tonic-gate 		pktp->cp_reason	= CPS_CHKERR;
6990Sstevel@tonic-gate 		return (DDI_FAILURE);
7000Sstevel@tonic-gate 	}
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate #ifdef ATA_DEBUG
7030Sstevel@tonic-gate 	if (pcata_debug & DENT) {
7040Sstevel@tonic-gate 		cmn_err(CE_CONT, "_go (%p) altstatus %x error %x\n",
705*7656SSherry.Moore@Sun.COM 		    (void *)unitp,
706*7656SSherry.Moore@Sun.COM 		    csx_Get8(softp->handle, AT_ALTSTATUS),
707*7656SSherry.Moore@Sun.COM 		    csx_Get8(softp->handle, AT_ERROR));
7080Sstevel@tonic-gate 		cmn_err(CE_CONT, "_go handle=%p\n", softp->handle);
7090Sstevel@tonic-gate 	}
7100Sstevel@tonic-gate #endif
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate 	/*
7130Sstevel@tonic-gate 	 * calculate drive address based on pktp->cp_srtsec
7140Sstevel@tonic-gate 	 */
7150Sstevel@tonic-gate 	start_sec	= pktp->cp_srtsec;
7160Sstevel@tonic-gate 	drvheads	= unitp->au_hd;
7170Sstevel@tonic-gate 	drvsectors	= unitp->au_sec;
7180Sstevel@tonic-gate 	resid		= start_sec / drvsectors;
7190Sstevel@tonic-gate 	head		= resid % drvheads;
7200Sstevel@tonic-gate 	cyl		= resid / drvheads;
7210Sstevel@tonic-gate 	nbytes		= min(pktp->cp_resid, pktp->ac_bytes_per_block);
7220Sstevel@tonic-gate 	ac_count	= (nbytes >> SCTRSHFT);
7230Sstevel@tonic-gate 	ac_devctl	= unitp->au_ctl_bits;
7240Sstevel@tonic-gate 	ac_sec		= (start_sec % drvsectors) + 1;
7250Sstevel@tonic-gate 	ac_hd		= head | unitp->au_drive_bits;
7260Sstevel@tonic-gate 	ac_lwcyl	= cyl;
7270Sstevel@tonic-gate 	ac_hicyl	= (cyl >> 8);
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate #ifdef ATA_DEBUG
7300Sstevel@tonic-gate 	if (pcata_debug & DIO) {
7310Sstevel@tonic-gate 		cmn_err(CE_CONT,
732*7656SSherry.Moore@Sun.COM 		    "_go %s at lba=%d (%uc %uh %us) "
733*7656SSherry.Moore@Sun.COM 		    "%d sectors cmd=%x ctl=%x\n",
734*7656SSherry.Moore@Sun.COM 		    (pktp->ac_direction == AT_OUT) ? "WT" : "RD",
735*7656SSherry.Moore@Sun.COM 		    start_sec, cyl, head, ac_sec,
736*7656SSherry.Moore@Sun.COM 		    ac_count,
737*7656SSherry.Moore@Sun.COM 		    pktp->ac_cmd, ac_devctl);
7380Sstevel@tonic-gate 	}
7390Sstevel@tonic-gate #endif
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 	if (pcata_wait(AT_ALTSTATUS, ATS_DRDY, ATS_BSY, softp))
7420Sstevel@tonic-gate 		return (DDI_FAILURE);
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	pcata_wait_complete(softp);
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_DEVCTL, ac_devctl);
7470Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_SECT, ac_sec);
7480Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_COUNT, ac_count);
7490Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_LCYL, ac_lwcyl);
7500Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_HCYL, ac_hicyl);
7510Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_DRVHD, ac_hd);
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 	/*
7540Sstevel@tonic-gate 	 * the command should make the controller status show BSY
7550Sstevel@tonic-gate 	 * the ISR intr_hi will not record status while the controller is BSY
7560Sstevel@tonic-gate 	 * therefore set interrupt expected state now
7570Sstevel@tonic-gate 	 * the next time we receive an interrupt and the controller is not BSY
7580Sstevel@tonic-gate 	 * the ISR will do the right thing
7590Sstevel@tonic-gate 	 */
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate 	mutex_enter(&softp->hi_mutex);
7620Sstevel@tonic-gate 	softp->intr_pending++;
7630Sstevel@tonic-gate 	if (pktp->ac_direction == AT_OUT)
7640Sstevel@tonic-gate 		softp->write_in_progress++;
7650Sstevel@tonic-gate 	csx_Put8(softp->handle, AT_CMD, pktp->ac_cmd);
7660Sstevel@tonic-gate 	mutex_exit(&softp->hi_mutex);
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 	/*
7690Sstevel@tonic-gate 	 * If there's data to go along with the command, send it now.
7700Sstevel@tonic-gate 	 */
7710Sstevel@tonic-gate 	if (pktp->ac_direction == AT_OUT) {
7720Sstevel@tonic-gate 		if (pcata_send_data(unitp, nbytes) == DDI_FAILURE) {
7730Sstevel@tonic-gate 			if (pktp->cp_retry >= RETRY_CNT) {
7740Sstevel@tonic-gate 				pcata_clear_queues(unitp);
7750Sstevel@tonic-gate 				return (DDI_FAILURE);
7760Sstevel@tonic-gate 			} else {
7770Sstevel@tonic-gate 				pktp->cp_retry++;
7780Sstevel@tonic-gate 				cmn_err(CE_CONT, "_go: write failure,"
7790Sstevel@tonic-gate 				    " retry=%d \n", pktp->cp_retry);
7800Sstevel@tonic-gate 				cmn_err(CE_CONT,
7810Sstevel@tonic-gate 				    "_go at lba=%d (%uc %uh %us) "
7820Sstevel@tonic-gate 				    "%d sectors cmd=%x ctl=%x \n",
7830Sstevel@tonic-gate 				    start_sec, cyl, head, ac_sec,
7840Sstevel@tonic-gate 				    ac_count,
7850Sstevel@tonic-gate 				    pktp->ac_cmd, ac_devctl);
7860Sstevel@tonic-gate 				return (PCATA_GO_RETRY);
7870Sstevel@tonic-gate 			}
7880Sstevel@tonic-gate 		}
7890Sstevel@tonic-gate 	}
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 	return (DDI_SUCCESS);
7920Sstevel@tonic-gate }
7930Sstevel@tonic-gate 
7940Sstevel@tonic-gate /*
7950Sstevel@tonic-gate  * return value
7960Sstevel@tonic-gate  *	success means go on o next block
7970Sstevel@tonic-gate  *	failure means continue with current block
7980Sstevel@tonic-gate  */
7990Sstevel@tonic-gate static void
pcata_iocmpl(ata_soft_t * softp)8000Sstevel@tonic-gate pcata_iocmpl(ata_soft_t *softp)
8010Sstevel@tonic-gate {
8020Sstevel@tonic-gate 	struct ata_cmpkt *pktp;
8030Sstevel@tonic-gate 	ata_unit_t	*unitp;
8040Sstevel@tonic-gate 	int		nbytes;
8050Sstevel@tonic-gate 	int		ret;
8060Sstevel@tonic-gate 	uchar_t		status;
8070Sstevel@tonic-gate 	uchar_t		error;
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 	ASSERT(mutex_owned(&softp->ata_mutex));
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	if (!CARD_PRESENT_VALID(softp)) {
8120Sstevel@tonic-gate 		cmn_err(CE_CONT, "?_iocmpl Device not present\n");
8130Sstevel@tonic-gate 		return;
8140Sstevel@tonic-gate 	}
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 	pktp = softp->ab_active;
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 	error = pktp->ac_error;
8190Sstevel@tonic-gate 	status = pktp->ac_status;
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 	unitp = (ata_unit_t *)pktp->cp_ctl_private;
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate 	/*
8240Sstevel@tonic-gate 	 * If there was an error, quit now
8250Sstevel@tonic-gate 	 * XXX/lcl no retry is attempted?
8260Sstevel@tonic-gate 	 */
8270Sstevel@tonic-gate 	if ((status & ATS_ERR) || (error & ATE_ABORT)) {
8280Sstevel@tonic-gate #ifdef ATA_DEBUG
8290Sstevel@tonic-gate 		if (pcata_debug & DIO)
8300Sstevel@tonic-gate 			cmn_err(CE_CONT,
831*7656SSherry.Moore@Sun.COM 			    "_iocmpl I/O error status=%04x error=%04x\n",
832*7656SSherry.Moore@Sun.COM 			    status,
833*7656SSherry.Moore@Sun.COM 			    error);
8340Sstevel@tonic-gate #endif
8350Sstevel@tonic-gate 		pktp->cp_reason = CPS_CHKERR;
8360Sstevel@tonic-gate 		return;
8370Sstevel@tonic-gate 	}
8380Sstevel@tonic-gate 
8390Sstevel@tonic-gate 	nbytes = min(pktp->cp_resid, pktp->ac_bytes_per_block);
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 	if (pktp->ac_direction == AT_IN) {
8420Sstevel@tonic-gate 		/*
8430Sstevel@tonic-gate 		 * do the read of the block
8440Sstevel@tonic-gate 		 */
8450Sstevel@tonic-gate 		ret = pcata_get_data(unitp, nbytes);
8460Sstevel@tonic-gate 		if (ret == DDI_FAILURE) {
8470Sstevel@tonic-gate 			/*
8480Sstevel@tonic-gate 			 * If the controller never presented the data
8490Sstevel@tonic-gate 			 * and the error bit isn't set,
8500Sstevel@tonic-gate 			 * there's a real problem.  Kill it now.
8510Sstevel@tonic-gate 			 */
8520Sstevel@tonic-gate 			pcata_clear_queues(unitp);
8530Sstevel@tonic-gate 			return;
8540Sstevel@tonic-gate 		}
8550Sstevel@tonic-gate 	}
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate 	/*
8580Sstevel@tonic-gate 	 * update counts...
8590Sstevel@tonic-gate 	 */
8600Sstevel@tonic-gate 	pktp->ac_v_addr += nbytes;
8610Sstevel@tonic-gate 	pktp->cp_resid -= nbytes;
8620Sstevel@tonic-gate 	pktp->cp_reason = CPS_SUCCESS;
8630Sstevel@tonic-gate 	pktp->cp_srtsec	+= (nbytes >> SCTRSHFT);
8640Sstevel@tonic-gate 
8650Sstevel@tonic-gate 	/* If last command was a GET_DEFECTS delay a bit */
8660Sstevel@tonic-gate 	if (pktp->ac_cmd == ATC_READDEFECTS)
8670Sstevel@tonic-gate 		drv_usecwait(1000);
8680Sstevel@tonic-gate }
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate int
pcata_intr_hi(ata_soft_t * softp)8710Sstevel@tonic-gate pcata_intr_hi(ata_soft_t *softp)
8720Sstevel@tonic-gate {
8730Sstevel@tonic-gate 	/*
8740Sstevel@tonic-gate 	 * In ata there is no hardware support to tell if the interrupt
8750Sstevel@tonic-gate 	 * belongs to ata or not. So no checks necessary here.  Later
8760Sstevel@tonic-gate 	 * will check the buffer and see if we have started a transaction.
8770Sstevel@tonic-gate 	 */
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate 	int		rval		= DDI_INTR_UNCLAIMED;
8800Sstevel@tonic-gate 	struct ata_cmpkt *pktp;
8810Sstevel@tonic-gate 	uchar_t		status;
8820Sstevel@tonic-gate 	uchar_t		error;
8830Sstevel@tonic-gate 
8840Sstevel@tonic-gate #ifdef ATA_DEBUG
8850Sstevel@tonic-gate 	if (pcata_debug & DENT) {
8860Sstevel@tonic-gate 		cmn_err(CE_CONT,
8870Sstevel@tonic-gate 		    "_intr_hi  sn=%d status=%x intr_pending=%d "
8880Sstevel@tonic-gate 		    "softint_pending=%d wr_in_prog=%d\n",
8890Sstevel@tonic-gate 		    softp->sn, csx_Get8(softp->handle, AT_ALTSTATUS),
8900Sstevel@tonic-gate 		    softp->intr_pending, softp->softint_pending,
8910Sstevel@tonic-gate 		    softp->write_in_progress);
8920Sstevel@tonic-gate 	}
8930Sstevel@tonic-gate #endif
8940Sstevel@tonic-gate 	mutex_enter(&softp->hi_mutex);
8950Sstevel@tonic-gate 
8960Sstevel@tonic-gate 	/*
8970Sstevel@tonic-gate 	 * this test is not redundant (don't remove it)
8980Sstevel@tonic-gate 	 * it is part of card removal processing
8990Sstevel@tonic-gate 	 * and prevents losing interrupt threads
9000Sstevel@tonic-gate 	 */
9010Sstevel@tonic-gate 	if (!CARD_PRESENT_VALID(softp)) {
9020Sstevel@tonic-gate 		mutex_exit(&softp->hi_mutex);
9030Sstevel@tonic-gate 		return (rval);
9040Sstevel@tonic-gate 	}
9050Sstevel@tonic-gate 
9060Sstevel@tonic-gate 	status = csx_Get8(softp->handle, AT_ALTSTATUS);
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 	/*
9090Sstevel@tonic-gate 	 * this is a shared interrupt
9100Sstevel@tonic-gate 	 * if the controller is NOT busy,
9110Sstevel@tonic-gate 	 *   and an interrupt is expected
9120Sstevel@tonic-gate 	 */
9130Sstevel@tonic-gate 
9140Sstevel@tonic-gate 	if ((status & ATS_ERR) &&
9150Sstevel@tonic-gate 	    ((status & ATS_BSY) == 0) &&
9160Sstevel@tonic-gate 	    (softp->intr_pending > 0)) {
9170Sstevel@tonic-gate 		cmn_err(CE_CONT,
918*7656SSherry.Moore@Sun.COM 		    "?_intr_hi  sn=%d status=%x\n",
919*7656SSherry.Moore@Sun.COM 		    softp->sn, status);
9200Sstevel@tonic-gate 		/* handle aborted commands */
9210Sstevel@tonic-gate 		error = csx_Get8(softp->handle, AT_ERROR);
9220Sstevel@tonic-gate 		if ((error & ATE_ABORT) &&
9230Sstevel@tonic-gate 		    (softp->write_in_progress > 0)) {
9240Sstevel@tonic-gate 			softp->write_in_progress = 0;
9250Sstevel@tonic-gate 		}
9260Sstevel@tonic-gate 	}
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 	if ((status & ATS_BSY) == 0 &&
9290Sstevel@tonic-gate 	    (softp->write_in_progress == 0) &&
9300Sstevel@tonic-gate 	    (softp->intr_pending > 0)) {
9310Sstevel@tonic-gate 		/*
9320Sstevel@tonic-gate 		 * Read the status register,
9330Sstevel@tonic-gate 		 * this clears an interrupt from the ata device
9340Sstevel@tonic-gate 		 */
9350Sstevel@tonic-gate 		status = csx_Get8(softp->handle, AT_STATUS);
9360Sstevel@tonic-gate 		error = csx_Get8(softp->handle, AT_ERROR);
9370Sstevel@tonic-gate 		rval = DDI_INTR_CLAIMED;
9380Sstevel@tonic-gate 		softp->intr_pending--;
9390Sstevel@tonic-gate 		/*
9400Sstevel@tonic-gate 		 * Make sure the interrupt is cleared, occasionally it is not
9410Sstevel@tonic-gate 		 * cleared by the first status read.
9420Sstevel@tonic-gate 		 */
9430Sstevel@tonic-gate 		status = csx_Get8(softp->handle, AT_STATUS);
9440Sstevel@tonic-gate 		/* put the error status in the right place */
9450Sstevel@tonic-gate 		if ((pktp = softp->ab_active) != 0) {
9460Sstevel@tonic-gate 			pktp->ac_error = error;
9470Sstevel@tonic-gate 			pktp->ac_status = status;
9480Sstevel@tonic-gate 		}
9490Sstevel@tonic-gate 	}
9500Sstevel@tonic-gate 	mutex_exit(&softp->hi_mutex);
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate #ifdef ATA_DEBUG
9530Sstevel@tonic-gate 	if (pcata_debug & DENT)
9540Sstevel@tonic-gate 		cmn_err(CE_CONT,
955*7656SSherry.Moore@Sun.COM 		    "_intr_hi status=%x error=%x claimed=%d pending=%d\n",
956*7656SSherry.Moore@Sun.COM 		    status, error,
957*7656SSherry.Moore@Sun.COM 		    (rval == DDI_INTR_CLAIMED),
958*7656SSherry.Moore@Sun.COM 		    softp->intr_pending);
9590Sstevel@tonic-gate #endif
9600Sstevel@tonic-gate 
9610Sstevel@tonic-gate 	if ((rval == DDI_INTR_CLAIMED) &&
9620Sstevel@tonic-gate 	    (softp->ab_active != NULL)) {
9630Sstevel@tonic-gate 		mutex_enter(&softp->hi_mutex);
9640Sstevel@tonic-gate 		softp->softint_pending++;
9650Sstevel@tonic-gate 		mutex_exit(&softp->hi_mutex);
9660Sstevel@tonic-gate 		ddi_trigger_softintr(softp->softint_id);
9670Sstevel@tonic-gate 	}
9680Sstevel@tonic-gate 
9690Sstevel@tonic-gate 	return (rval);
9700Sstevel@tonic-gate }
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate uint32_t
pcata_intr(char * parm)9730Sstevel@tonic-gate pcata_intr(char *parm)
9740Sstevel@tonic-gate {
9750Sstevel@tonic-gate 	ata_soft_t	*softp = (ata_soft_t *)parm;
9760Sstevel@tonic-gate 	ata_unit_t	*unitp;
9770Sstevel@tonic-gate 	struct ata_cmpkt *pktp;
9780Sstevel@tonic-gate 	buf_t		*bp;
9790Sstevel@tonic-gate 	uint32_t	nbytes;
9800Sstevel@tonic-gate 	uint32_t	start_sec;
9810Sstevel@tonic-gate 	uint32_t	cyl;
9820Sstevel@tonic-gate 	uint32_t	resid;
9830Sstevel@tonic-gate 	uchar_t		head;
9840Sstevel@tonic-gate 	uchar_t		drvheads;
9850Sstevel@tonic-gate 	uchar_t		drvsectors;
9860Sstevel@tonic-gate 	uchar_t		ac_devctl;
9870Sstevel@tonic-gate 	uchar_t		ac_sec;
9880Sstevel@tonic-gate 	uchar_t		ac_count;
9890Sstevel@tonic-gate 	int		ret;
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate #ifdef ATA_DEBUG
9920Sstevel@tonic-gate 	if (pcata_debug & DENT) {
9930Sstevel@tonic-gate 		cmn_err(CE_CONT, "_intr entry (%p) sn=%d softint_pending=%d\n",
9940Sstevel@tonic-gate 		    (void *)softp, softp->sn, softp->softint_pending);
9950Sstevel@tonic-gate 	}
9960Sstevel@tonic-gate #endif
9970Sstevel@tonic-gate 
9980Sstevel@tonic-gate 
9990Sstevel@tonic-gate 	if (softp->softint_pending == 0) {
10000Sstevel@tonic-gate 		return (DDI_INTR_UNCLAIMED);
10010Sstevel@tonic-gate 	}
10020Sstevel@tonic-gate 
10030Sstevel@tonic-gate 	mutex_enter(&softp->ata_mutex);
10040Sstevel@tonic-gate 
10050Sstevel@tonic-gate 	if (softp->ab_active == NULL) {
10060Sstevel@tonic-gate 		cmn_err(CE_CONT, "?_intr No outstanding I/O\n");
10070Sstevel@tonic-gate 		goto done;
10080Sstevel@tonic-gate 	}
10090Sstevel@tonic-gate 
10100Sstevel@tonic-gate 	/* perform I/O completion */
10110Sstevel@tonic-gate 	pcata_iocmpl(softp);
10120Sstevel@tonic-gate 
10130Sstevel@tonic-gate 	if (!CARD_PRESENT_VALID(softp))
10140Sstevel@tonic-gate 		goto done;
10150Sstevel@tonic-gate 
10160Sstevel@tonic-gate 	/*
10170Sstevel@tonic-gate 	 * if packet is done (either errors or all bytes transfered)
10180Sstevel@tonic-gate 	 *	pktp points to current packet
10190Sstevel@tonic-gate 	 *	ab_active is cleared
10200Sstevel@tonic-gate 	 * else
10210Sstevel@tonic-gate 	 *	pktp is null
10220Sstevel@tonic-gate 	 *	ab_active is unchanged
10230Sstevel@tonic-gate 	 */
10240Sstevel@tonic-gate 	pktp = softp->ab_active;
10250Sstevel@tonic-gate 	if (pktp != NULL) {
10260Sstevel@tonic-gate 		if (pktp->cp_resid == 0 || pktp->cp_reason != CPS_SUCCESS) {
10270Sstevel@tonic-gate #ifdef ATA_DEBUG
10280Sstevel@tonic-gate 			if (pcata_debug & DENT) {
10290Sstevel@tonic-gate 				cmn_err(CE_CONT, "_intr retry=%d reason=%d"
10300Sstevel@tonic-gate 				    " CPS_SUCCESS=%d pkpt=%p cp_resid = %d\n",
10310Sstevel@tonic-gate 				    pktp->cp_retry, pktp->cp_reason,
10320Sstevel@tonic-gate 				    CPS_SUCCESS, (void *)pktp,
10330Sstevel@tonic-gate 				    pktp->cp_resid);
10340Sstevel@tonic-gate 			}
10350Sstevel@tonic-gate #endif
10360Sstevel@tonic-gate 			if ((pktp->cp_retry < RETRY_CNT) &&
10370Sstevel@tonic-gate 			    (pktp->cp_reason != CPS_SUCCESS)) {
10380Sstevel@tonic-gate 				pktp->cp_retry++;
10390Sstevel@tonic-gate 				unitp = softp->ab_active->cp_ctl_private;
10400Sstevel@tonic-gate 
10410Sstevel@tonic-gate 				/*
10420Sstevel@tonic-gate 				 * calculate drive address based on
10430Sstevel@tonic-gate 				 * pktp->cp_srtsec
10440Sstevel@tonic-gate 				 */
10450Sstevel@tonic-gate 				start_sec = pktp->cp_srtsec;
10460Sstevel@tonic-gate 				drvheads = unitp->au_hd;
10470Sstevel@tonic-gate 				drvsectors = unitp->au_sec;
10480Sstevel@tonic-gate 				resid = start_sec / drvsectors;
10490Sstevel@tonic-gate 				head = resid % drvheads;
10500Sstevel@tonic-gate 				cyl = resid / drvheads;
10510Sstevel@tonic-gate 				nbytes = min(pktp->cp_resid,
10520Sstevel@tonic-gate 				    pktp->ac_bytes_per_block);
10530Sstevel@tonic-gate 				ac_count = (nbytes >> SCTRSHFT);
10540Sstevel@tonic-gate 				ac_devctl = unitp->au_ctl_bits;
10550Sstevel@tonic-gate 				ac_sec = (start_sec % drvsectors) + 1;
10560Sstevel@tonic-gate 
10570Sstevel@tonic-gate 				cmn_err(CE_CONT, "_intr I/O failure,"
10580Sstevel@tonic-gate 				    " retry %d\n", pktp->cp_retry);
10590Sstevel@tonic-gate 				cmn_err(CE_CONT,
10600Sstevel@tonic-gate 				    "_intr %s at lba=%d (%uc %uh %us) "
10610Sstevel@tonic-gate 				    "%d sectors cmd=%x ctl=%x\n",
10620Sstevel@tonic-gate 				    (pktp->ac_direction == AT_OUT) ?
10630Sstevel@tonic-gate 				    "write" : "read",
10640Sstevel@tonic-gate 				    start_sec, cyl, head, ac_sec,
10650Sstevel@tonic-gate 				    ac_count,
10660Sstevel@tonic-gate 				    pktp->ac_cmd, ac_devctl);
10670Sstevel@tonic-gate 
10680Sstevel@tonic-gate 				pktp = 0;
10690Sstevel@tonic-gate 			} else {
10700Sstevel@tonic-gate 				/* I/O is complete or an error has occured */
10710Sstevel@tonic-gate 				softp->ab_active = NULL;
10720Sstevel@tonic-gate 			}
10730Sstevel@tonic-gate 		} else {
10740Sstevel@tonic-gate 			/* I/O is still in progress */
10750Sstevel@tonic-gate 			pktp = 0;
10760Sstevel@tonic-gate 		}
10770Sstevel@tonic-gate 	}
10780Sstevel@tonic-gate 
10790Sstevel@tonic-gate 	/*
10800Sstevel@tonic-gate 	 * packet which caused this interrupt is now complete
10810Sstevel@tonic-gate 	 */
10820Sstevel@tonic-gate 	if (pktp) {
10830Sstevel@tonic-gate 		if ((pktp->ac_status & ATS_ERR) || (pktp->ac_error)) {
10840Sstevel@tonic-gate 			bioerror(pktp->cp_bp, EIO);
10850Sstevel@tonic-gate #ifdef  ATA_DEBUG
10860Sstevel@tonic-gate 			cmn_err(CE_NOTE, "_intr ATA ERROR status=%x error=%x\n",
10870Sstevel@tonic-gate 			    pktp->ac_status, pktp->ac_error);
10880Sstevel@tonic-gate #endif
10890Sstevel@tonic-gate 		}
10900Sstevel@tonic-gate 
10910Sstevel@tonic-gate 		bp =  pktp->cp_bp;
10920Sstevel@tonic-gate 		bp->b_resid = bp->b_bcount - pktp->cp_bytexfer;
10930Sstevel@tonic-gate 
10940Sstevel@tonic-gate 		/* release the thread for the I/O just completed */
10950Sstevel@tonic-gate 		biodone(bp);
10960Sstevel@tonic-gate 
10970Sstevel@tonic-gate 		kmem_free((void *)pktp, sizeof (*pktp));
10980Sstevel@tonic-gate 	}
10990Sstevel@tonic-gate 
11000Sstevel@tonic-gate 
11010Sstevel@tonic-gate 	/* if ab_active is NULL attempt to dequeue next I/O request */
11020Sstevel@tonic-gate 	if (softp->ab_active == NULL && softp->ab_head != NULL) {
11030Sstevel@tonic-gate 		softp->ab_active = softp->ab_head;
11040Sstevel@tonic-gate 		softp->ab_head = softp->ab_head->pkt_forw;
11050Sstevel@tonic-gate 
11060Sstevel@tonic-gate #ifdef ATA_DEBUG
11070Sstevel@tonic-gate 		if (pcata_debug & DIO) {
11080Sstevel@tonic-gate 			cmn_err(CE_CONT,
1109*7656SSherry.Moore@Sun.COM 			    "_start_next_cmd current:%p head:%p\n",
1110*7656SSherry.Moore@Sun.COM 			    (void *)softp->ab_active,
1111*7656SSherry.Moore@Sun.COM 			    (void *)softp->ab_head);
11120Sstevel@tonic-gate 		}
11130Sstevel@tonic-gate #endif
11140Sstevel@tonic-gate 	}
11150Sstevel@tonic-gate 
11160Sstevel@tonic-gate 	mutex_enter(&softp->hi_mutex);
11170Sstevel@tonic-gate 	softp->softint_pending--;
11180Sstevel@tonic-gate 	mutex_exit(&softp->hi_mutex);
11190Sstevel@tonic-gate 
11200Sstevel@tonic-gate 	/* if ab_active is not NULL, attempt to initiate I/O */
11210Sstevel@tonic-gate 	if (softp->ab_active != NULL) {
11220Sstevel@tonic-gate 		unitp = softp->ab_active->cp_ctl_private;
11230Sstevel@tonic-gate 
11240Sstevel@tonic-gate 		ret = PCATA_GO_RETRY;
11250Sstevel@tonic-gate 		while (ret == PCATA_GO_RETRY) {
11260Sstevel@tonic-gate 			ret = pcata_go(unitp);
11270Sstevel@tonic-gate 		}
11280Sstevel@tonic-gate 	}
11290Sstevel@tonic-gate 	goto exit;
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate done:
11320Sstevel@tonic-gate 	mutex_enter(&softp->hi_mutex);
11330Sstevel@tonic-gate 	softp->softint_pending--;
11340Sstevel@tonic-gate 	mutex_exit(&softp->hi_mutex);
11350Sstevel@tonic-gate exit:
11360Sstevel@tonic-gate 	mutex_exit(&softp->ata_mutex);
11370Sstevel@tonic-gate #ifdef ATA_DEBUG
11380Sstevel@tonic-gate 	if (pcata_debug & DENT)
11390Sstevel@tonic-gate 		cmn_err(CE_CONT, "_intr exit (%p)\n", (void *)softp);
11400Sstevel@tonic-gate #endif
11410Sstevel@tonic-gate 	return (DDI_INTR_CLAIMED);
11420Sstevel@tonic-gate }
11430Sstevel@tonic-gate 
11440Sstevel@tonic-gate 
11450Sstevel@tonic-gate /*
11460Sstevel@tonic-gate  * XXX/lcl need determine if all drives or a single drive is to be cleared
11470Sstevel@tonic-gate  * if all drives then eliminate tests for pktp->cp_ctl_private == unitp
11480Sstevel@tonic-gate  * if single drive then examine usage of flag ATA_OFFLINE
11490Sstevel@tonic-gate  */
11500Sstevel@tonic-gate static void
pcata_clear_queues(ata_unit_t * unitp)11510Sstevel@tonic-gate pcata_clear_queues(ata_unit_t *unitp)
11520Sstevel@tonic-gate {
11530Sstevel@tonic-gate 	ata_soft_t	*softp = unitp->a_blkp;
11540Sstevel@tonic-gate 	struct ata_cmpkt *pktp;
11550Sstevel@tonic-gate 	buf_t		*bp;
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate 	ASSERT(mutex_owned(&softp->ata_mutex));
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate #ifdef ATA_DEBUG
11600Sstevel@tonic-gate 	if (pcata_debug & DENT) {
11610Sstevel@tonic-gate 		cmn_err(CE_CONT, "_clear_queues (%p)\n", (void *)unitp);
11620Sstevel@tonic-gate 	}
11630Sstevel@tonic-gate #endif
11640Sstevel@tonic-gate 	/*
11650Sstevel@tonic-gate 	 * nack the active request
11660Sstevel@tonic-gate 	 */
11670Sstevel@tonic-gate 	softp->ab_status_flag |= ATA_OFFLINE;
11680Sstevel@tonic-gate 
11690Sstevel@tonic-gate 	pktp = softp->ab_active;
11700Sstevel@tonic-gate 	if (pktp && pktp->cp_ctl_private == unitp)
11710Sstevel@tonic-gate 		pcata_nack_packet(pktp);
11720Sstevel@tonic-gate 
11730Sstevel@tonic-gate 	/*
11740Sstevel@tonic-gate 	 * now nack all queued requests
11750Sstevel@tonic-gate 	 */
11760Sstevel@tonic-gate 	for (pktp = softp->ab_head; pktp; pktp = pktp->pkt_forw) {
11770Sstevel@tonic-gate 		bp =  pktp->cp_bp;
11780Sstevel@tonic-gate 		if (bp && ((bp->b_flags & B_DONE) == 0)) {
11790Sstevel@tonic-gate 			if ((pktp->ac_status & ATS_ERR) || (pktp->ac_error)) {
11800Sstevel@tonic-gate 				bioerror(bp, EIO);
11810Sstevel@tonic-gate 			}
11820Sstevel@tonic-gate 
11830Sstevel@tonic-gate 			/* release the thread for the I/O */
11840Sstevel@tonic-gate 			biodone(bp);
11850Sstevel@tonic-gate 		}
11860Sstevel@tonic-gate 		if (pktp->cp_ctl_private == unitp)
11870Sstevel@tonic-gate 			pcata_nack_packet(pktp);
11880Sstevel@tonic-gate 	}
11890Sstevel@tonic-gate }
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate static void
pcata_nack_packet(struct ata_cmpkt * pktp)11920Sstevel@tonic-gate pcata_nack_packet(struct ata_cmpkt *pktp)
11930Sstevel@tonic-gate {
11940Sstevel@tonic-gate #ifdef ATA_DEBUG
11950Sstevel@tonic-gate 	if (pcata_debug & DENT)
11960Sstevel@tonic-gate 		cmn_err(CE_CONT, "pcata_nack_packet (%p)\n", (void *)pktp);
11970Sstevel@tonic-gate #endif
11980Sstevel@tonic-gate 	if (pktp != NULL) {
11990Sstevel@tonic-gate 		pktp->cp_reason = CPS_CHKERR;
12000Sstevel@tonic-gate 		pktp->ac_scb = DERR_ABORT;
12010Sstevel@tonic-gate 	}
12020Sstevel@tonic-gate }
12030Sstevel@tonic-gate 
12040Sstevel@tonic-gate /*
12050Sstevel@tonic-gate  * pcata_wait --  wait for a register of a controller to achieve a
12060Sstevel@tonic-gate  *		specific state.  Arguments are a mask of bits we care about,
12070Sstevel@tonic-gate  *		and two sub-masks.  To return normally, all the bits in the
12080Sstevel@tonic-gate  *		first sub-mask must be ON, all the bits in the second sub-
12090Sstevel@tonic-gate  *		mask must be OFF.  If 5 seconds pass without the controller
12100Sstevel@tonic-gate  *		achieving the desired bit configuration, we return 1, else
12110Sstevel@tonic-gate  *		0.
12120Sstevel@tonic-gate  */
12130Sstevel@tonic-gate static int
pcata_wait(uint32_t port,ushort_t onbits,ushort_t offbits,ata_soft_t * softp)12140Sstevel@tonic-gate pcata_wait(uint32_t port, ushort_t onbits, ushort_t offbits, ata_soft_t *softp)
12150Sstevel@tonic-gate {
12160Sstevel@tonic-gate 	register int	i;
12170Sstevel@tonic-gate 	register ushort_t maskval;
12180Sstevel@tonic-gate 	int	ival = csx_Get8(softp->handle, port);
12190Sstevel@tonic-gate 
12200Sstevel@tonic-gate 	for (i = 400000; i && (CARD_PRESENT_VALID(softp)); i--) {
12210Sstevel@tonic-gate 		maskval = csx_Get8(softp->handle, port);
12220Sstevel@tonic-gate 		if (((maskval & onbits) == onbits) &&
1223*7656SSherry.Moore@Sun.COM 		    ((maskval & offbits) == 0))
12240Sstevel@tonic-gate 			return (0);
12250Sstevel@tonic-gate 		drv_usecwait(10);
12260Sstevel@tonic-gate 	}
12270Sstevel@tonic-gate #ifdef ATA_DEBUG
12280Sstevel@tonic-gate 	cmn_err(CE_CONT, "_wait timeout: "
12290Sstevel@tonic-gate 	    "sn=%d port=%x on: 0x%x off: 0x%x ival: 0x%x  eval: 0x%x\n",
12300Sstevel@tonic-gate 	    softp->sn, port, onbits, offbits, ival, maskval);
12310Sstevel@tonic-gate #endif
12320Sstevel@tonic-gate 	return (1);
12330Sstevel@tonic-gate }
12340Sstevel@tonic-gate 
12350Sstevel@tonic-gate 
12360Sstevel@tonic-gate /*
12370Sstevel@tonic-gate  * Similar to pcata_wait but the timeout is much shorter.  It is only used
12380Sstevel@tonic-gate  * during initialization when long delays are noticable.
12390Sstevel@tonic-gate  */
12400Sstevel@tonic-gate static int
pcata_wait1(uint32_t port,ushort_t onbits,ushort_t offbits,int interval,ata_soft_t * softp)12410Sstevel@tonic-gate pcata_wait1(uint32_t port, ushort_t onbits, ushort_t offbits, int interval,
12420Sstevel@tonic-gate 		ata_soft_t *softp)
12430Sstevel@tonic-gate {
12440Sstevel@tonic-gate 	register int	i;
12450Sstevel@tonic-gate 	register ushort_t maskval;
12460Sstevel@tonic-gate 
12470Sstevel@tonic-gate 	for (i = interval; i && (CARD_PRESENT_VALID(softp)); i--) {
12480Sstevel@tonic-gate 		maskval = csx_Get8(softp->handle, port);
12490Sstevel@tonic-gate 		if (((maskval & onbits) == onbits) &&
1250*7656SSherry.Moore@Sun.COM 		    ((maskval & offbits) == 0))
12510Sstevel@tonic-gate 			return (0);
12520Sstevel@tonic-gate 		drv_usecwait(10);
12530Sstevel@tonic-gate 	}
12540Sstevel@tonic-gate 	return (1);
12550Sstevel@tonic-gate }
12560Sstevel@tonic-gate 
12570Sstevel@tonic-gate /*
12580Sstevel@tonic-gate  * Wait until the command interrupt has been serviced before starting
12590Sstevel@tonic-gate  * another command.
12600Sstevel@tonic-gate  *
12610Sstevel@tonic-gate  */
12620Sstevel@tonic-gate static void
pcata_wait_complete(ata_soft_t * softp)12630Sstevel@tonic-gate pcata_wait_complete(ata_soft_t *softp)
12640Sstevel@tonic-gate {
12650Sstevel@tonic-gate 	int	i;
12660Sstevel@tonic-gate 
12670Sstevel@tonic-gate 	for (i = 0; i < PCATA_WAIT_CNT &&
12680Sstevel@tonic-gate 	    ((softp->intr_pending > 0) || (softp->softint_pending > 0)); i++) {
12690Sstevel@tonic-gate 		drv_usecwait(10);
12700Sstevel@tonic-gate 	}
12710Sstevel@tonic-gate }
12720Sstevel@tonic-gate 
12730Sstevel@tonic-gate static int
pcata_send_data(ata_unit_t * unitp,int count)12740Sstevel@tonic-gate pcata_send_data(ata_unit_t *unitp, int count)
12750Sstevel@tonic-gate {
12760Sstevel@tonic-gate 	ata_soft_t	*softp = unitp->a_blkp;
12770Sstevel@tonic-gate 	struct ata_cmpkt *pktp = unitp->a_blkp->ab_active;
12780Sstevel@tonic-gate 
12790Sstevel@tonic-gate #ifdef ATA_DEBUG
12800Sstevel@tonic-gate 	if (pcata_debug & DENT) {
12810Sstevel@tonic-gate 		cmn_err(CE_CONT, "_send_data (%p, %x)\n",
1282*7656SSherry.Moore@Sun.COM 		    (void *)unitp, count);
12830Sstevel@tonic-gate 	}
12840Sstevel@tonic-gate #endif
12850Sstevel@tonic-gate 	if (pcata_wait(AT_ALTSTATUS, ATS_DRQ, 0, softp)) {
12860Sstevel@tonic-gate 		cmn_err(CE_CONT, "_send_data - NOT READY\n");
12870Sstevel@tonic-gate 		mutex_enter(&softp->hi_mutex);
12880Sstevel@tonic-gate 		softp->write_in_progress = 0;
12890Sstevel@tonic-gate 		mutex_exit(&softp->hi_mutex);
12900Sstevel@tonic-gate 		return (DDI_FAILURE);
12910Sstevel@tonic-gate 	}
12920Sstevel@tonic-gate 
12930Sstevel@tonic-gate 	/*
12940Sstevel@tonic-gate 	 * copy count bytes from pktp->v_addr to the data port
12950Sstevel@tonic-gate 	 */
12960Sstevel@tonic-gate #ifdef ATA_DEBUG
12970Sstevel@tonic-gate 	if (pcata_debug & DIO) {
12980Sstevel@tonic-gate 		cmn_err(CE_CONT, "_send_data: port=%x addr=0x%p count=0x%x\n",
1299*7656SSherry.Moore@Sun.COM 		    unitp->a_blkp->ab_data,
1300*7656SSherry.Moore@Sun.COM 		    (void *)pktp->ac_v_addr,
1301*7656SSherry.Moore@Sun.COM 		    count);
13020Sstevel@tonic-gate 	}
13030Sstevel@tonic-gate #endif
13040Sstevel@tonic-gate 
13050Sstevel@tonic-gate 	if (!CARD_PRESENT_VALID(softp)) {
13060Sstevel@tonic-gate 		mutex_enter(&softp->hi_mutex);
13070Sstevel@tonic-gate 		softp->write_in_progress = 0;
13080Sstevel@tonic-gate 		mutex_exit(&softp->hi_mutex);
13090Sstevel@tonic-gate 		return (DDI_FAILURE);
13100Sstevel@tonic-gate 	}
13110Sstevel@tonic-gate 
13120Sstevel@tonic-gate 	mutex_enter(&softp->hi_mutex);
13130Sstevel@tonic-gate 	csx_RepPut16(softp->handle, (ushort_t *)pktp->ac_v_addr, AT_DATA,
1314*7656SSherry.Moore@Sun.COM 	    (count >> 1), DDI_DEV_NO_AUTOINCR);
13150Sstevel@tonic-gate 	if (softp->write_in_progress > 0)
13160Sstevel@tonic-gate 		softp->write_in_progress--;
13170Sstevel@tonic-gate 	mutex_exit(&softp->hi_mutex);
13180Sstevel@tonic-gate 
13190Sstevel@tonic-gate #ifdef ATA_DEBUG
13200Sstevel@tonic-gate 	if (pcata_debug & DIO) {
13210Sstevel@tonic-gate 		cmn_err(CE_CONT, "_send_data: ");
13220Sstevel@tonic-gate 		pcata_print_sttflag(csx_Get8(softp->handle, AT_ALTSTATUS));
13230Sstevel@tonic-gate 	}
13240Sstevel@tonic-gate 
13250Sstevel@tonic-gate #endif
13260Sstevel@tonic-gate 	return (DDI_SUCCESS);
13270Sstevel@tonic-gate }
13280Sstevel@tonic-gate 
13290Sstevel@tonic-gate 
13300Sstevel@tonic-gate static int
pcata_get_data(ata_unit_t * unitp,int count)13310Sstevel@tonic-gate pcata_get_data(ata_unit_t *unitp, int count)
13320Sstevel@tonic-gate {
13330Sstevel@tonic-gate 	ata_soft_t	*softp = unitp->a_blkp;
13340Sstevel@tonic-gate 	register struct ata_cmpkt *pktp = unitp->a_blkp->ab_active;
13350Sstevel@tonic-gate 
13360Sstevel@tonic-gate 	if (pcata_wait(AT_ALTSTATUS, ATS_DRQ, 0, softp)) {
13370Sstevel@tonic-gate 		cmn_err(CE_CONT, "_get_data - NOT READY\n");
13380Sstevel@tonic-gate 		return (DDI_FAILURE);
13390Sstevel@tonic-gate 	}
13400Sstevel@tonic-gate 	/*
13410Sstevel@tonic-gate 	 * copy count bytes from the data port to pktp->ac_v_addr
13420Sstevel@tonic-gate 	 */
13430Sstevel@tonic-gate 
13440Sstevel@tonic-gate #ifdef ATA_DEBUG
13450Sstevel@tonic-gate 	if (pcata_debug & DIO) {
13460Sstevel@tonic-gate 		cmn_err(CE_CONT, "_get_data port=%x addr=0x%p count=0x%x\n",
13470Sstevel@tonic-gate 		    unitp->a_blkp->ab_data, (void *)pktp->ac_v_addr, count);
13480Sstevel@tonic-gate 	}
13490Sstevel@tonic-gate #endif
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate 	if (!CARD_PRESENT_VALID(softp))
13520Sstevel@tonic-gate 		return (DDI_FAILURE);
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate 	csx_RepGet8(softp->handle, (uchar_t *)pktp->ac_v_addr,
1355*7656SSherry.Moore@Sun.COM 	    AT_DATA, count, DDI_DEV_NO_AUTOINCR);
13560Sstevel@tonic-gate 
13570Sstevel@tonic-gate #ifdef ATA_DEBUG
13580Sstevel@tonic-gate 	if (pcata_debug & DIO)
13590Sstevel@tonic-gate 		cmn_err(CE_CONT, "_get_data complete\n");
13600Sstevel@tonic-gate #endif
13610Sstevel@tonic-gate 	return (DDI_SUCCESS);
13620Sstevel@tonic-gate }
13630Sstevel@tonic-gate 
13640Sstevel@tonic-gate 
13650Sstevel@tonic-gate int
pcata_getedt(ata_soft_t * softp,int dmax)13660Sstevel@tonic-gate pcata_getedt(ata_soft_t *softp, int dmax)
13670Sstevel@tonic-gate {
13680Sstevel@tonic-gate 	ushort_t *secbuf;
13690Sstevel@tonic-gate 	struct atarpbuf	*rpbp;
13700Sstevel@tonic-gate 	int drive, dcount;
13710Sstevel@tonic-gate 	char buf[41];
13720Sstevel@tonic-gate 	int i;
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate #ifdef ATA_DEBUG
13750Sstevel@tonic-gate 	if (pcata_debug & DENT) {
13760Sstevel@tonic-gate 		cmn_err(CE_CONT, "_getedt (%p)\n", (void *)softp);
13770Sstevel@tonic-gate 	}
13780Sstevel@tonic-gate #endif
13790Sstevel@tonic-gate 	/* toggle reset bit to trigger a software reset		*/
13800Sstevel@tonic-gate 	if (!(CARD_PRESENT_VALID(softp)))
13810Sstevel@tonic-gate 		return (DDI_FAILURE);
13820Sstevel@tonic-gate 	csx_Put8(softp->handle, AT_DEVCTL, AT_DEVCTL_D3|AT_SRST);
13830Sstevel@tonic-gate 
13840Sstevel@tonic-gate 	drv_usecwait(1000);
13850Sstevel@tonic-gate 	if (!(CARD_PRESENT_VALID(softp)))
13860Sstevel@tonic-gate 		return (DDI_FAILURE);
13870Sstevel@tonic-gate 
13880Sstevel@tonic-gate 	/*
13890Sstevel@tonic-gate 	 * The interrupt disable command does not work reliably with
13900Sstevel@tonic-gate 	 * all PC ATA cards. It is better to leave interupts enabled
13910Sstevel@tonic-gate 	 * and process them as they occur.
13920Sstevel@tonic-gate 	 */
13930Sstevel@tonic-gate 
13940Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_DEVCTL, ENABLE_INTERRUPT);
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate 	secbuf = (ushort_t *)kmem_zalloc(NBPSCTR, KM_NOSLEEP);
13970Sstevel@tonic-gate 	if (!secbuf) {
13980Sstevel@tonic-gate 		return (DDI_FAILURE);
13990Sstevel@tonic-gate 	}
14000Sstevel@tonic-gate 
14010Sstevel@tonic-gate 	for (dcount = drive = 0; drive < dmax; drive++) {
14020Sstevel@tonic-gate 		if (!(rpbp = (struct atarpbuf *)kmem_zalloc(
1403*7656SSherry.Moore@Sun.COM 		    (sizeof (struct atarpbuf) +
14040Sstevel@tonic-gate 				sizeof (struct scsi_inquiry)), KM_NOSLEEP))) {
14050Sstevel@tonic-gate 			kmem_free(secbuf, NBPSCTR);
14060Sstevel@tonic-gate 			return (DDI_FAILURE);
14070Sstevel@tonic-gate 		}
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 		/*
14100Sstevel@tonic-gate 		 * load up with the drive number
14110Sstevel@tonic-gate 		 */
14120Sstevel@tonic-gate 		if (drive == 0) {
14130Sstevel@tonic-gate 			PCIDE_OUTB(softp->handle, AT_DRVHD, ATDH_DRIVE0);
14140Sstevel@tonic-gate 		} else {
14150Sstevel@tonic-gate 			PCIDE_OUTB(softp->handle, AT_DRVHD, ATDH_DRIVE1);
14160Sstevel@tonic-gate 		}
14170Sstevel@tonic-gate 		PCIDE_OUTB(softp->handle, AT_FEATURE, 0);
14180Sstevel@tonic-gate 
14190Sstevel@tonic-gate 		softp->ab_dev_type[drive] = pcata_drive_type(softp, secbuf);
14200Sstevel@tonic-gate 
14210Sstevel@tonic-gate 		if (softp->ab_dev_type[drive] == ATA_DEV_NONE) {
14220Sstevel@tonic-gate 			kmem_free(rpbp, (sizeof (struct atarpbuf) +
1423*7656SSherry.Moore@Sun.COM 			    sizeof (struct scsi_inquiry)));
14240Sstevel@tonic-gate 			continue;
14250Sstevel@tonic-gate 		}
14260Sstevel@tonic-gate 		dcount++;
14270Sstevel@tonic-gate 		bcopy((caddr_t)secbuf, (caddr_t)rpbp, sizeof (struct atarpbuf));
14280Sstevel@tonic-gate 
14290Sstevel@tonic-gate 		mutex_enter(&softp->ata_mutex);
14300Sstevel@tonic-gate 		if (!(softp->card_state & PCATA_CARD_INSERTED)) {
14310Sstevel@tonic-gate 			kmem_free(rpbp, (sizeof (struct atarpbuf) +
1432*7656SSherry.Moore@Sun.COM 			    sizeof (struct scsi_inquiry)));
14330Sstevel@tonic-gate 			dcount--;
14340Sstevel@tonic-gate 			mutex_exit(&softp->ata_mutex);
14350Sstevel@tonic-gate 			break;
14360Sstevel@tonic-gate 		}
14370Sstevel@tonic-gate 
14380Sstevel@tonic-gate 		softp->ab_rpbp[drive] = rpbp;
14390Sstevel@tonic-gate 
14400Sstevel@tonic-gate 		/*
14410Sstevel@tonic-gate 		 * We need to swap the strings on both platforms.
14420Sstevel@tonic-gate 		 */
14430Sstevel@tonic-gate #ifdef _BIG_ENDIAN
14440Sstevel@tonic-gate 		pcata_byte_swap((char *)rpbp, sizeof (*rpbp));
14450Sstevel@tonic-gate #else
14460Sstevel@tonic-gate 		pcata_byte_swap(rpbp->atarp_drvser,
1447*7656SSherry.Moore@Sun.COM 		    sizeof (rpbp->atarp_drvser));
14480Sstevel@tonic-gate 		pcata_byte_swap(rpbp->atarp_fw, sizeof (rpbp->atarp_fw));
14490Sstevel@tonic-gate 		pcata_byte_swap(rpbp->atarp_model, sizeof (rpbp->atarp_model));
14500Sstevel@tonic-gate #endif
14510Sstevel@tonic-gate 
14520Sstevel@tonic-gate 		mutex_exit(&softp->ata_mutex);
14530Sstevel@tonic-gate 
14540Sstevel@tonic-gate #ifdef	ATA_DEBUG
14550Sstevel@tonic-gate 		if (pcata_debug & DINIT) {
14560Sstevel@tonic-gate 			(void) strncpy(buf,
1457*7656SSherry.Moore@Sun.COM 			    rpbp->atarp_model, sizeof (rpbp->atarp_model));
14580Sstevel@tonic-gate 		buf[sizeof (rpbp->atarp_model)-1] = '\0';
14590Sstevel@tonic-gate 
14600Sstevel@tonic-gate 		/* truncate model */
14610Sstevel@tonic-gate 		for (i = sizeof (rpbp->atarp_model) - 2; i && buf[i] == ' ';
1462*7656SSherry.Moore@Sun.COM 		    i--) {
14630Sstevel@tonic-gate 			buf[i] = '\0';
14640Sstevel@tonic-gate 		}
14650Sstevel@tonic-gate 		cmn_err(CE_CONT, "_getedt model %s, targ %d, stat %x, err %x\n",
1466*7656SSherry.Moore@Sun.COM 		    buf,
1467*7656SSherry.Moore@Sun.COM 		    drive,
1468*7656SSherry.Moore@Sun.COM 		    csx_Get8(softp->handle, AT_STATUS),
1469*7656SSherry.Moore@Sun.COM 		    csx_Get8(softp->handle, AT_ERROR));
14700Sstevel@tonic-gate 		cmn_err(CE_CONT, "	cfg 0x%x, cyl %d, hd %d, sec/trk %d\n",
1471*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_config,
1472*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_fixcyls,
1473*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_heads,
1474*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_sectors);
14750Sstevel@tonic-gate 		cmn_err(CE_CONT, "	mult1 0x%x, mult2 0x%x, dwcap 0x%x,"
1476*7656SSherry.Moore@Sun.COM 		    " cap 0x%x\n",
1477*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_mult1,
1478*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_mult2,
1479*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_dwcap,
1480*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_cap);
14810Sstevel@tonic-gate 		cmn_err(CE_CONT, "	piomode 0x%x, dmamode 0x%x,"
1482*7656SSherry.Moore@Sun.COM 		    " advpiomode 0x%x\n",
1483*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_piomode,
1484*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_dmamode,
1485*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_advpiomode);
14860Sstevel@tonic-gate 		cmn_err(CE_CONT, "	minpio %d, minpioflow %d",
1487*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_minpio,
1488*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_minpioflow);
14890Sstevel@tonic-gate 		cmn_err(CE_CONT, " valid 0x%x, dwdma 0x%x\n",
1490*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_validinfo,
1491*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_dworddma);
14920Sstevel@tonic-gate 		}
14930Sstevel@tonic-gate #endif
14940Sstevel@tonic-gate 
14950Sstevel@tonic-gate 		if (!(CARD_PRESENT_VALID(softp)))
14960Sstevel@tonic-gate 			return (DDI_FAILURE);
14970Sstevel@tonic-gate 		(void) csx_Get8(softp->handle, AT_STATUS);
14980Sstevel@tonic-gate 		(void) csx_Get8(softp->handle, AT_ERROR);
14990Sstevel@tonic-gate 	}
15000Sstevel@tonic-gate 
15010Sstevel@tonic-gate 	kmem_free(secbuf, NBPSCTR);
15020Sstevel@tonic-gate 	if (dcount == 0)
15030Sstevel@tonic-gate 		return (DDI_FAILURE);
15040Sstevel@tonic-gate 
15050Sstevel@tonic-gate 	for (dcount = drive = 0; drive < dmax; drive++) {
15060Sstevel@tonic-gate 
15070Sstevel@tonic-gate 		if ((rpbp = softp->ab_rpbp[drive]) == NULL) {
15080Sstevel@tonic-gate 			continue; /* no drive here */
15090Sstevel@tonic-gate 		}
15100Sstevel@tonic-gate 
15110Sstevel@tonic-gate 		if (softp->ab_dev_type[drive] != ATA_DEV_DISK) {
15120Sstevel@tonic-gate 			cmn_err(CE_CONT, "Unknown IDE attachment at 0x%x.\n",
1513*7656SSherry.Moore@Sun.COM 			    softp->ab_cmd - AT_CMD);
15140Sstevel@tonic-gate 			continue;
15150Sstevel@tonic-gate 		}
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate 		/*
15180Sstevel@tonic-gate 		 * feed some of the info back in a set_params call.
15190Sstevel@tonic-gate 		 */
15200Sstevel@tonic-gate 		mutex_enter(&softp->ata_mutex);
15210Sstevel@tonic-gate 		if (pcata_setpar(drive, rpbp->atarp_heads,
1522*7656SSherry.Moore@Sun.COM 		    rpbp->atarp_sectors, softp)
1523*7656SSherry.Moore@Sun.COM 		    == DDI_FAILURE) {
15240Sstevel@tonic-gate 			/*
15250Sstevel@tonic-gate 			 * there should have been a drive here but it
15260Sstevel@tonic-gate 			 * didn't respond properly. It stayed BUSY.
15270Sstevel@tonic-gate 			 */
15280Sstevel@tonic-gate 			if (softp->ab_rpbp[drive]) {
15290Sstevel@tonic-gate 				kmem_free(rpbp,
1530*7656SSherry.Moore@Sun.COM 				    (sizeof (struct atarpbuf) +
1531*7656SSherry.Moore@Sun.COM 				    sizeof (struct scsi_inquiry)));
15320Sstevel@tonic-gate 			}
15330Sstevel@tonic-gate 			softp->ab_rpbp[drive] = NULL;
15340Sstevel@tonic-gate 			softp->ab_dev_type[drive] = ATA_DEV_NONE;
15350Sstevel@tonic-gate 			mutex_exit(&softp->ata_mutex);
15360Sstevel@tonic-gate 			continue;
15370Sstevel@tonic-gate 		}
15380Sstevel@tonic-gate 		mutex_exit(&softp->ata_mutex);
15390Sstevel@tonic-gate 		dcount++;
15400Sstevel@tonic-gate 	}
15410Sstevel@tonic-gate 
15420Sstevel@tonic-gate #ifdef ATA_DEBUG
15430Sstevel@tonic-gate 	if (pcata_debug)
15440Sstevel@tonic-gate 		cmn_err(CE_CONT, "**** probed %d device%s 0x%x\n",
1545*7656SSherry.Moore@Sun.COM 		    dcount, dcount == 1 ? "." : "s.",
1546*7656SSherry.Moore@Sun.COM 		    softp->ab_cmd - AT_CMD);
15470Sstevel@tonic-gate #endif
15480Sstevel@tonic-gate 
15490Sstevel@tonic-gate 	return (dcount ? DDI_SUCCESS : DDI_FAILURE);
15500Sstevel@tonic-gate }
15510Sstevel@tonic-gate 
15520Sstevel@tonic-gate /*
15530Sstevel@tonic-gate  * pcata_drive_type()
15540Sstevel@tonic-gate  */
15550Sstevel@tonic-gate static uchar_t
pcata_drive_type(ata_soft_t * softp,ushort_t * buf)15560Sstevel@tonic-gate pcata_drive_type(ata_soft_t *softp, ushort_t *buf)
15570Sstevel@tonic-gate {
15580Sstevel@tonic-gate 	struct atarpbuf	*rpbp = (struct atarpbuf *)buf;
15590Sstevel@tonic-gate 
15600Sstevel@tonic-gate 	if (pcata_wait1(AT_ALTSTATUS,
15610Sstevel@tonic-gate 	    (ATS_DRDY | ATS_DSC), (ATS_BSY | ATS_ERR), 100000, softp))
15620Sstevel@tonic-gate 		return (ATA_DEV_NONE);
15630Sstevel@tonic-gate 
15640Sstevel@tonic-gate 	pcata_wait_complete(softp);
15650Sstevel@tonic-gate 
15660Sstevel@tonic-gate 	/*
15670Sstevel@tonic-gate 	 * note: pcata_drive_type is only called by pcata_getedt()
15680Sstevel@tonic-gate 	 * the drive (master/slave) is selected there
15690Sstevel@tonic-gate 	 */
15700Sstevel@tonic-gate 	/* command also known as IDENTIFY DEVICE */
15710Sstevel@tonic-gate 	mutex_enter(&softp->hi_mutex);
15720Sstevel@tonic-gate 	softp->intr_pending++;
15730Sstevel@tonic-gate 	csx_Put8(softp->handle, AT_CMD, ATC_READPARMS);
15740Sstevel@tonic-gate 	mutex_exit(&softp->hi_mutex);
15750Sstevel@tonic-gate 
15760Sstevel@tonic-gate 	if (pcata_wait1(AT_ALTSTATUS, ATS_DRQ, ATS_BSY, 1000000, softp)) {
15770Sstevel@tonic-gate 
15780Sstevel@tonic-gate #ifdef ATA_DEBUG
15790Sstevel@tonic-gate 		if (pcata_debug) {
15800Sstevel@tonic-gate 			cmn_err(CE_NOTE, "failed drive did not settle:");
15810Sstevel@tonic-gate 			pcata_print_sttflag(csx_Get8(softp->handle, AT_STATUS));
15820Sstevel@tonic-gate 		}
15830Sstevel@tonic-gate #endif
15840Sstevel@tonic-gate 		return (ATA_DEV_NONE);
15850Sstevel@tonic-gate 	}
15860Sstevel@tonic-gate 
15870Sstevel@tonic-gate 	csx_RepGet16(softp->handle, (ushort_t *)buf, AT_DATA, NBPSCTR >> 1,
1588*7656SSherry.Moore@Sun.COM 	    DDI_DEV_NO_AUTOINCR);
15890Sstevel@tonic-gate 
15900Sstevel@tonic-gate #ifdef ATA_DEBUG
15910Sstevel@tonic-gate 	if (pcata_debug) {
15920Sstevel@tonic-gate 		if ((csx_Get8(softp->handle, AT_STATUS) & ATS_ERR) == 0) {
15930Sstevel@tonic-gate 			pcata_byte_swap(rpbp->atarp_model,
1594*7656SSherry.Moore@Sun.COM 			    sizeof (rpbp->atarp_model));
15950Sstevel@tonic-gate 			rpbp->atarp_model[sizeof (rpbp->atarp_model)-1] = '\0';
15960Sstevel@tonic-gate 			cmn_err(CE_CONT, "succeeded: %s\n",
1597*7656SSherry.Moore@Sun.COM 			    rpbp->atarp_model);
15980Sstevel@tonic-gate 			pcata_byte_swap(rpbp->atarp_model,
1599*7656SSherry.Moore@Sun.COM 			    sizeof (rpbp->atarp_model));
16000Sstevel@tonic-gate 		} else {
16010Sstevel@tonic-gate 			cmn_err(CE_CONT, "failed drive drive read error.\n");
16020Sstevel@tonic-gate 		}
16030Sstevel@tonic-gate 	}
16040Sstevel@tonic-gate #endif
16050Sstevel@tonic-gate 
16060Sstevel@tonic-gate 	/*
16070Sstevel@tonic-gate 	 * wait for the drive to recognize I've read all the data.  some
16080Sstevel@tonic-gate 	 * drives have been observed to take as much as 3msec to finish
16090Sstevel@tonic-gate 	 * sending the data; allow 5 msec just in case.
16100Sstevel@tonic-gate 	 */
16110Sstevel@tonic-gate 	if (pcata_wait1(AT_ALTSTATUS, ATS_DRDY, ATS_BSY | ATS_DRQ, 500, softp))
16120Sstevel@tonic-gate 		return (ATA_DEV_NONE);
16130Sstevel@tonic-gate 
16140Sstevel@tonic-gate 	if (!CARD_PRESENT_VALID(softp))
16150Sstevel@tonic-gate 		return (ATA_DEV_NONE);
16160Sstevel@tonic-gate 
16170Sstevel@tonic-gate 	if (csx_Get8(softp->handle, AT_ALTSTATUS) & ATS_ERR)
16180Sstevel@tonic-gate 		return (ATA_DEV_NONE);
16190Sstevel@tonic-gate 
16200Sstevel@tonic-gate 	return (ATA_DEV_DISK);
16210Sstevel@tonic-gate }
16220Sstevel@tonic-gate 
16230Sstevel@tonic-gate 
16240Sstevel@tonic-gate /*
16250Sstevel@tonic-gate  * Drive set params command.
16260Sstevel@tonic-gate  */
16270Sstevel@tonic-gate static int
pcata_setpar(int drive,int heads,int sectors,ata_soft_t * softp)16280Sstevel@tonic-gate pcata_setpar(int drive, int heads, int sectors, ata_soft_t *softp)
16290Sstevel@tonic-gate {
16300Sstevel@tonic-gate 
16310Sstevel@tonic-gate #ifdef ATA_DEBUG
16320Sstevel@tonic-gate 	if (pcata_debug & DINIT)
16330Sstevel@tonic-gate 		cmn_err(CE_CONT, "_setpar status=0x%x drive=%d heads=%d\n",
1634*7656SSherry.Moore@Sun.COM 		    csx_Get8(softp->handle, AT_STATUS), drive, heads);
16350Sstevel@tonic-gate #endif
16360Sstevel@tonic-gate 	if (!CARD_PRESENT_VALID(softp))
16370Sstevel@tonic-gate 		return (DDI_FAILURE);
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate 	if (pcata_wait(AT_ALTSTATUS, ATS_DRDY, ATS_BSY, softp))
16400Sstevel@tonic-gate 		return (DDI_FAILURE);
16410Sstevel@tonic-gate 
16420Sstevel@tonic-gate 	pcata_wait_complete(softp);
16430Sstevel@tonic-gate 
16440Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_DRVHD, (heads - 1) |
1645*7656SSherry.Moore@Sun.COM 	    (drive == 0 ? ATDH_DRIVE0 : ATDH_DRIVE1));
16460Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_COUNT, sectors);
16470Sstevel@tonic-gate 
16480Sstevel@tonic-gate 	mutex_enter(&softp->hi_mutex);
16490Sstevel@tonic-gate 	softp->intr_pending++;
16500Sstevel@tonic-gate 	csx_Put8(softp->handle, AT_CMD, ATC_SETPARAM);
16510Sstevel@tonic-gate 	mutex_exit(&softp->hi_mutex);
16520Sstevel@tonic-gate 
16530Sstevel@tonic-gate 	if (pcata_wait(AT_ALTSTATUS, 0, ATS_BSY, softp))
16540Sstevel@tonic-gate 		return (DDI_FAILURE);
16550Sstevel@tonic-gate 	return (DDI_SUCCESS);
16560Sstevel@tonic-gate }
16570Sstevel@tonic-gate 
16580Sstevel@tonic-gate void
pcata_byte_swap(char * buf,int n)16590Sstevel@tonic-gate pcata_byte_swap(char *buf, int n)
16600Sstevel@tonic-gate {
16610Sstevel@tonic-gate 	int	i;
16620Sstevel@tonic-gate 	char	c;
16630Sstevel@tonic-gate 
16640Sstevel@tonic-gate 	n &= ~1;
16650Sstevel@tonic-gate 	for (i = 0; i < n; i += 2) {
16660Sstevel@tonic-gate 		c = buf[i];
16670Sstevel@tonic-gate 		buf[i] = buf[i + 1];
16680Sstevel@tonic-gate 		buf[i + 1] = c;
16690Sstevel@tonic-gate 	}
16700Sstevel@tonic-gate }
16710Sstevel@tonic-gate 
16720Sstevel@tonic-gate 
16730Sstevel@tonic-gate int
pcata_set_rw_multiple(ata_soft_t * softp,int drive)16740Sstevel@tonic-gate pcata_set_rw_multiple(ata_soft_t *softp, int drive)
16750Sstevel@tonic-gate {
16760Sstevel@tonic-gate 	int	i;
16770Sstevel@tonic-gate 	int	laststat;
16780Sstevel@tonic-gate 	char	size;
16790Sstevel@tonic-gate 	char	accepted_size = -1;
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate #ifdef ATA_DEBUG
16820Sstevel@tonic-gate 	if (pcata_debug & DENT) {
16830Sstevel@tonic-gate 		cmn_err(CE_CONT, "_set_rw_multiple (%p, %d)\n",
1684*7656SSherry.Moore@Sun.COM 		    (void *)softp, drive);
16850Sstevel@tonic-gate 	}
16860Sstevel@tonic-gate #endif
16870Sstevel@tonic-gate 
16880Sstevel@tonic-gate 	if (!CARD_PRESENT_VALID(softp))
16890Sstevel@tonic-gate 		return (DDI_FAILURE);
16900Sstevel@tonic-gate 	/*
16910Sstevel@tonic-gate 	 * Assume we're going to use read/write multiple until the controller
16920Sstevel@tonic-gate 	 * says it doesn't understand them.
16930Sstevel@tonic-gate 	 */
16940Sstevel@tonic-gate 	softp->ab_rd_cmd[drive] = ATC_RDMULT;
16950Sstevel@tonic-gate 	softp->ab_wr_cmd[drive] = ATC_WRMULT;
16960Sstevel@tonic-gate 
16970Sstevel@tonic-gate 	/*
16980Sstevel@tonic-gate 	 * set drive number
16990Sstevel@tonic-gate 	 */
17000Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_DRVHD, drive == 0 ? ATDH_DRIVE0 :
1701*7656SSherry.Moore@Sun.COM 	    ATDH_DRIVE1);
17020Sstevel@tonic-gate 
17030Sstevel@tonic-gate 	for (size = 32; size > 0 && accepted_size == -1 &&
1704*7656SSherry.Moore@Sun.COM 	    CARD_PRESENT_VALID(softp); size >>= 1) {
17050Sstevel@tonic-gate 
17060Sstevel@tonic-gate 		if (pcata_wait(AT_ALTSTATUS, ATS_DRDY, ATS_BSY, softp))
17070Sstevel@tonic-gate 			return (DDI_FAILURE);
17080Sstevel@tonic-gate 
17090Sstevel@tonic-gate 		pcata_wait_complete(softp);
17100Sstevel@tonic-gate 
17110Sstevel@tonic-gate 		/*
17120Sstevel@tonic-gate 		 * send the command
17130Sstevel@tonic-gate 		 */
17140Sstevel@tonic-gate 		PCIDE_OUTB(softp->handle, AT_COUNT, size);
17150Sstevel@tonic-gate 
17160Sstevel@tonic-gate 		mutex_enter(&softp->hi_mutex);
17170Sstevel@tonic-gate 		softp->intr_pending++;
17180Sstevel@tonic-gate 		csx_Put8(softp->handle, AT_CMD, ATC_SETMULT);
17190Sstevel@tonic-gate 		mutex_exit(&softp->hi_mutex);
17200Sstevel@tonic-gate 
17210Sstevel@tonic-gate 		if (pcata_wait(AT_ALTSTATUS, 0, ATS_BSY, softp))
17220Sstevel@tonic-gate 			/*
17230Sstevel@tonic-gate 			 * there should have been a drive here but it
17240Sstevel@tonic-gate 			 * didn't respond properly. It stayed BUSY.
17250Sstevel@tonic-gate 			 * complete failure!
17260Sstevel@tonic-gate 			 */
17270Sstevel@tonic-gate 			return (DDI_FAILURE);
17280Sstevel@tonic-gate 		/*
17290Sstevel@tonic-gate 		 * Wait for DRDY or error status
17300Sstevel@tonic-gate 		 */
17310Sstevel@tonic-gate 		for (i = 0; i < ATA_LOOP_CNT && CARD_PRESENT_VALID(softp);
1732*7656SSherry.Moore@Sun.COM 		    i++) {
17330Sstevel@tonic-gate 			if (((laststat = csx_Get8(softp->handle, AT_ALTSTATUS))
1734*7656SSherry.Moore@Sun.COM 			    & (ATS_DRDY | ATS_ERR)) != 0)
17350Sstevel@tonic-gate 				break;
17360Sstevel@tonic-gate 			drv_usecwait(10);
17370Sstevel@tonic-gate 		}
17380Sstevel@tonic-gate 		if (i == ATA_LOOP_CNT)
17390Sstevel@tonic-gate 			/*
17400Sstevel@tonic-gate 			 * Didn't get ready OR error...  complete failure!
17410Sstevel@tonic-gate 			 * there should have been a drive here but it
17420Sstevel@tonic-gate 			 * didn't respond properly. It didn't set ERR or DRQ.
17430Sstevel@tonic-gate 			 */
17440Sstevel@tonic-gate 			return (DDI_FAILURE);
17450Sstevel@tonic-gate 
17460Sstevel@tonic-gate 		/*
17470Sstevel@tonic-gate 		 * See if DRQ or error
17480Sstevel@tonic-gate 		 */
17490Sstevel@tonic-gate 		if (laststat & ATS_ERR) {
17500Sstevel@tonic-gate 			/*
17510Sstevel@tonic-gate 			 * there should have been a drive here but it
17520Sstevel@tonic-gate 			 * didn't respond properly. There was an error.
17530Sstevel@tonic-gate 			 * Try the next value.
17540Sstevel@tonic-gate 			 */
17550Sstevel@tonic-gate 			continue;
17560Sstevel@tonic-gate 		}
17570Sstevel@tonic-gate 		/*
17580Sstevel@tonic-gate 		 * Got ready.. use the value that worked.
17590Sstevel@tonic-gate 		 */
17600Sstevel@tonic-gate 		accepted_size = size;
17610Sstevel@tonic-gate 	}
17620Sstevel@tonic-gate 	if (accepted_size == -1) {
17630Sstevel@tonic-gate 		/*
17640Sstevel@tonic-gate 		 * None of the values worked...
17650Sstevel@tonic-gate 		 * the controller responded correctly though so it probably
17660Sstevel@tonic-gate 		 * doesn't support the read/write multiple commands.
17670Sstevel@tonic-gate 		 */
17680Sstevel@tonic-gate 
17690Sstevel@tonic-gate #ifdef ATA_DEBUG
17700Sstevel@tonic-gate 		if (pcata_debug & DENT) {
17710Sstevel@tonic-gate 			cmn_err(CE_CONT, "Using STD R/W cmds and setting"
1772*7656SSherry.Moore@Sun.COM 			    "block factor to 1\n");
17730Sstevel@tonic-gate 		}
17740Sstevel@tonic-gate #endif
17750Sstevel@tonic-gate 		softp->ab_rd_cmd[drive] = ATC_RDSEC;
17760Sstevel@tonic-gate 		softp->ab_wr_cmd[drive] = ATC_WRSEC;
17770Sstevel@tonic-gate 		softp->ab_block_factor[drive] = 1;
17780Sstevel@tonic-gate 		softp->ab_max_transfer = 1;
17790Sstevel@tonic-gate 		return (DDI_SUCCESS);
17800Sstevel@tonic-gate 	}
17810Sstevel@tonic-gate 	if (accepted_size == 1) {
17820Sstevel@tonic-gate 		/*
17830Sstevel@tonic-gate 		 * OK... Leave it at 1
17840Sstevel@tonic-gate 		 */
17850Sstevel@tonic-gate #ifdef ATA_DEBUG
17860Sstevel@tonic-gate 		if (pcata_debug & DENT) {
17870Sstevel@tonic-gate 			cmn_err(CE_CONT, "setting block factor to 1\n");
17880Sstevel@tonic-gate 		}
17890Sstevel@tonic-gate #endif
17900Sstevel@tonic-gate 		softp->ab_block_factor[drive] = accepted_size;
17910Sstevel@tonic-gate 		softp->ab_max_transfer = accepted_size;
17920Sstevel@tonic-gate 		return (DDI_SUCCESS);
17930Sstevel@tonic-gate 	}
17940Sstevel@tonic-gate 	accepted_size >>= 1;
17950Sstevel@tonic-gate 	/*
17960Sstevel@tonic-gate 	 * Allow a user specified block factor to override the system chosen
17970Sstevel@tonic-gate 	 * value.  Only allow the user to reduce the value.
17980Sstevel@tonic-gate 	 * -1 indicates the user didn't specify anything
17990Sstevel@tonic-gate 	 */
18000Sstevel@tonic-gate 	if ((softp->ab_block_factor[drive] != -1) &&
18010Sstevel@tonic-gate 	    (softp->ab_block_factor[drive] < accepted_size))
18020Sstevel@tonic-gate 		accepted_size = softp->ab_block_factor[drive];
18030Sstevel@tonic-gate 
18040Sstevel@tonic-gate 	if (pcata_wait(AT_ALTSTATUS, ATS_DRDY, ATS_BSY, softp))
18050Sstevel@tonic-gate 		return (DDI_FAILURE);
18060Sstevel@tonic-gate 
18070Sstevel@tonic-gate 	pcata_wait_complete(softp);
18080Sstevel@tonic-gate 
18090Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_COUNT, accepted_size);
18100Sstevel@tonic-gate 
18110Sstevel@tonic-gate 	mutex_enter(&softp->hi_mutex);
18120Sstevel@tonic-gate 	softp->intr_pending++;
18130Sstevel@tonic-gate 	csx_Put8(softp->handle, AT_CMD, ATC_SETMULT);
18140Sstevel@tonic-gate 	mutex_exit(&softp->hi_mutex);
18150Sstevel@tonic-gate 
18160Sstevel@tonic-gate 	if (pcata_wait(AT_ALTSTATUS, 0, ATS_BSY, softp))
18170Sstevel@tonic-gate 		/*
18180Sstevel@tonic-gate 		 * there should have been a drive here but it
18190Sstevel@tonic-gate 		 * didn't respond properly. It stayed BUSY.
18200Sstevel@tonic-gate 		 */
18210Sstevel@tonic-gate 		return (DDI_FAILURE);
18220Sstevel@tonic-gate 
18230Sstevel@tonic-gate #ifdef ATA_DEBUG
18240Sstevel@tonic-gate 	if (pcata_debug & DENT) {
18250Sstevel@tonic-gate 		cmn_err(CE_CONT, "setting block factor for drive %d to %d\n",
18260Sstevel@tonic-gate 		    drive, accepted_size);
18270Sstevel@tonic-gate 	}
18280Sstevel@tonic-gate #endif
18290Sstevel@tonic-gate 
18300Sstevel@tonic-gate 	softp->ab_block_factor[drive] = accepted_size;
18310Sstevel@tonic-gate 	return (DDI_SUCCESS);
18320Sstevel@tonic-gate }
18330Sstevel@tonic-gate 
18340Sstevel@tonic-gate static int
pcata_dump(dev_t dev,caddr_t addr,daddr_t blkno,int nblk)18350Sstevel@tonic-gate pcata_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk)
18360Sstevel@tonic-gate {
18370Sstevel@tonic-gate 	ata_soft_t *softp;
18380Sstevel@tonic-gate 	buf_t *bp;
18390Sstevel@tonic-gate 	void *instance;
18400Sstevel@tonic-gate 
18410Sstevel@tonic-gate 
18420Sstevel@tonic-gate 	if (pcata_getinfo(NULL, DDI_INFO_DEVT2INSTANCE, (void *)dev,
18430Sstevel@tonic-gate 	    &instance) != DDI_SUCCESS)
18440Sstevel@tonic-gate 		return (ENODEV);
18450Sstevel@tonic-gate 
18460Sstevel@tonic-gate 	softp = ddi_get_soft_state(pcata_soft, (int)(uintptr_t)instance);
18470Sstevel@tonic-gate 	if (!softp) {
18480Sstevel@tonic-gate 		return (ENXIO);
18490Sstevel@tonic-gate 	}
18500Sstevel@tonic-gate 
18510Sstevel@tonic-gate 	if (!CARD_PRESENT_VALID(softp))
18520Sstevel@tonic-gate 		return (ENODEV);
18530Sstevel@tonic-gate 
18540Sstevel@tonic-gate 	bp = softp->crashbuf;
18550Sstevel@tonic-gate 	bp->b_un.b_addr = addr;
18560Sstevel@tonic-gate 	bp->b_edev = dev;
18570Sstevel@tonic-gate 	bp->b_dev = cmpdev(dev);
18580Sstevel@tonic-gate 	bp->b_bcount = nblk * DEV_BSIZE;
18590Sstevel@tonic-gate 	bp->b_flags |= B_WRITE | B_PHYS;
18600Sstevel@tonic-gate 	bp->b_blkno = blkno;
18610Sstevel@tonic-gate 	bp->b_private = 0;
18620Sstevel@tonic-gate 
18630Sstevel@tonic-gate 	/*
18640Sstevel@tonic-gate 	 * If pcata_strategy() encounters an exception, or card_removal
18650Sstevel@tonic-gate 	 * is called, before this is complete, it is possible that
18660Sstevel@tonic-gate 	 * biodone will be called but the buffer (bp) wont
18670Sstevel@tonic-gate 	 * be released unless B_ASYNC flag is set. So
18680Sstevel@tonic-gate 	 * don't set B_ASYNC flag unless you mean it.
18690Sstevel@tonic-gate 	 */
18700Sstevel@tonic-gate 	(void) pcata_strategy(bp);
18710Sstevel@tonic-gate 	if (bp->b_error)
18720Sstevel@tonic-gate 		return (bp->b_error);
18730Sstevel@tonic-gate 
18740Sstevel@tonic-gate 	for (;;) {
18750Sstevel@tonic-gate 		if (!CARD_PRESENT_VALID(softp))
18760Sstevel@tonic-gate 			return (ENODEV);
18770Sstevel@tonic-gate 		if (bp->b_flags & B_DONE) {
18780Sstevel@tonic-gate 			if (bp->b_flags & B_ERROR)
18790Sstevel@tonic-gate 				return (bp->b_error);
18800Sstevel@tonic-gate 			else
18810Sstevel@tonic-gate 				return (0);
18820Sstevel@tonic-gate 		}
18830Sstevel@tonic-gate 		drv_usecwait(1000);
18840Sstevel@tonic-gate 	}
18850Sstevel@tonic-gate }
18860Sstevel@tonic-gate 
18870Sstevel@tonic-gate /* ddi print */
18880Sstevel@tonic-gate static int
pcata_print(dev_t dev,char * str)18890Sstevel@tonic-gate pcata_print(dev_t dev, char *str)
18900Sstevel@tonic-gate {
18910Sstevel@tonic-gate 	void	*instance;
18920Sstevel@tonic-gate 	ata_soft_t *softp;
18930Sstevel@tonic-gate 
18940Sstevel@tonic-gate 
18950Sstevel@tonic-gate 	/* get instance number */
18960Sstevel@tonic-gate 	if (pcata_getinfo(NULL, DDI_INFO_DEVT2INSTANCE, (void *)dev,
18970Sstevel@tonic-gate 	    &instance) != DDI_SUCCESS) {
18980Sstevel@tonic-gate 		cmn_err(CE_CONT, "_print: pcata_getinfo"
1899*7656SSherry.Moore@Sun.COM 		    "return ENODEV\n");
19000Sstevel@tonic-gate 		return (ENODEV);
19010Sstevel@tonic-gate 	}
19020Sstevel@tonic-gate 
19030Sstevel@tonic-gate 	if (!(softp = ddi_get_soft_state(pcata_soft,
19040Sstevel@tonic-gate 	    (int)(uintptr_t)instance))) {
19050Sstevel@tonic-gate 		return (ENXIO);
19060Sstevel@tonic-gate 	}
19070Sstevel@tonic-gate 
19080Sstevel@tonic-gate 	cmn_err(CE_NOTE, "_print: socket %d %s", softp->sn, str);
19090Sstevel@tonic-gate 	return (0);
19100Sstevel@tonic-gate 
19110Sstevel@tonic-gate }
19120Sstevel@tonic-gate 
19130Sstevel@tonic-gate static int
pcata_rdrw(dev_t dev,struct uio * uio,int flag)19140Sstevel@tonic-gate pcata_rdrw(dev_t dev, struct uio *uio, int flag)
19150Sstevel@tonic-gate {
19160Sstevel@tonic-gate 	return (physio(pcata_strategy, (buf_t *)0, dev, flag, pcata_min, uio));
19170Sstevel@tonic-gate }
19180Sstevel@tonic-gate 
19190Sstevel@tonic-gate 
19200Sstevel@tonic-gate 
19210Sstevel@tonic-gate /* ARGSUSED2 */
19220Sstevel@tonic-gate static int
pcata_read(dev_t dev,struct uio * uio,cred_t * cred_p)19230Sstevel@tonic-gate pcata_read(dev_t dev, struct uio *uio, cred_t *cred_p)
19240Sstevel@tonic-gate {
19250Sstevel@tonic-gate 	return (pcata_rdrw(dev, uio, B_READ));
19260Sstevel@tonic-gate }
19270Sstevel@tonic-gate 
19280Sstevel@tonic-gate 
19290Sstevel@tonic-gate 
19300Sstevel@tonic-gate /* ARGSUSED2 */
19310Sstevel@tonic-gate static int
pcata_write(dev_t dev,struct uio * uio,cred_t * cred_p)19320Sstevel@tonic-gate pcata_write(dev_t dev, struct uio *uio, cred_t *cred_p)
19330Sstevel@tonic-gate {
19340Sstevel@tonic-gate 	return (pcata_rdrw(dev, uio, B_WRITE));
19350Sstevel@tonic-gate }
19360Sstevel@tonic-gate 
19370Sstevel@tonic-gate 
19380Sstevel@tonic-gate void
pcata_min(buf_t * bp)19390Sstevel@tonic-gate pcata_min(buf_t *bp)
19400Sstevel@tonic-gate {
19410Sstevel@tonic-gate 	ata_soft_t *softp;
19420Sstevel@tonic-gate 	void *instance;
19430Sstevel@tonic-gate 
19440Sstevel@tonic-gate 	if (pcata_getinfo(NULL, DDI_INFO_DEVT2INSTANCE, (void *)bp->b_edev,
19450Sstevel@tonic-gate 	    &instance) != DDI_SUCCESS)
19460Sstevel@tonic-gate 		cmn_err(CE_CONT, "Error in pcata_min\n");
19470Sstevel@tonic-gate 
19480Sstevel@tonic-gate 	softp = ddi_get_soft_state(pcata_soft, (int)(uintptr_t)instance);
19490Sstevel@tonic-gate 
19500Sstevel@tonic-gate 	if ((ROUNDUP(bp->b_bcount, NBPSCTR) >> SCTRSHFT) >
1951*7656SSherry.Moore@Sun.COM 	    softp->ab_max_transfer)
19520Sstevel@tonic-gate 
19530Sstevel@tonic-gate 		bp->b_bcount = softp->ab_max_transfer << SCTRSHFT;
19540Sstevel@tonic-gate }
19550Sstevel@tonic-gate 
19560Sstevel@tonic-gate static void
pcata_iosetup(ata_unit_t * unitp,struct ata_cmpkt * pktp)19570Sstevel@tonic-gate pcata_iosetup(ata_unit_t *unitp, struct ata_cmpkt *pktp)
19580Sstevel@tonic-gate {
19590Sstevel@tonic-gate 	uint32_t	sec_count;
19600Sstevel@tonic-gate 
19610Sstevel@tonic-gate #ifdef ATA_DEBUG
19620Sstevel@tonic-gate 	if (pcata_debug & DENT) {
19630Sstevel@tonic-gate 		cmn_err(CE_CONT, "_iosetup (%p, %p)\n",
1964*7656SSherry.Moore@Sun.COM 		    (void *)unitp, (void *)pktp);
19650Sstevel@tonic-gate 	}
19660Sstevel@tonic-gate #endif
19670Sstevel@tonic-gate 
19680Sstevel@tonic-gate 	/* check for error retry */
19690Sstevel@tonic-gate 	if (pktp->ac_flags & CFLAG_ERROR) {
19700Sstevel@tonic-gate 		pktp->ac_bytes_per_block = NBPSCTR;
19710Sstevel@tonic-gate 		sec_count = 1;
19720Sstevel@tonic-gate 	} else {
19730Sstevel@tonic-gate 		/*
19740Sstevel@tonic-gate 		 * Limit requetst to ab_max_transfer sectors.
19750Sstevel@tonic-gate 		 * The value is specified by the user in the
19760Sstevel@tonic-gate 		 * max_transfer property. It must be in the range 1 to 256.
19770Sstevel@tonic-gate 		 * When max_transfer is 0x100 it is bigger than 8 bits.
19780Sstevel@tonic-gate 		 * The spec says 0 represents 256 so it should be OK.
19790Sstevel@tonic-gate 		 */
19800Sstevel@tonic-gate 		sec_count = min((pktp->cp_bytexfer >> SCTRSHFT),
19810Sstevel@tonic-gate 		    unitp->a_blkp->ab_max_transfer);
19820Sstevel@tonic-gate 	}
19830Sstevel@tonic-gate 	pktp->ac_v_addr = pktp->ac_start_v_addr;
19840Sstevel@tonic-gate 	pktp->cp_resid = pktp->cp_bytexfer;
19850Sstevel@tonic-gate 	pktp->cp_bytexfer = sec_count << SCTRSHFT;
19860Sstevel@tonic-gate 
19870Sstevel@tonic-gate #ifdef ATA_DEBUG
19880Sstevel@tonic-gate 	if (pcata_debug & DIO) {
19890Sstevel@tonic-gate 		cmn_err(CE_CONT,
1990*7656SSherry.Moore@Sun.COM 		    "_iosetup: asking for start 0x%lx count 0x%x\n",
1991*7656SSherry.Moore@Sun.COM 		    pktp->cp_srtsec, pktp->cp_bytexfer >> SCTRSHFT);
19920Sstevel@tonic-gate 	}
19930Sstevel@tonic-gate #endif
19940Sstevel@tonic-gate 	/*
19950Sstevel@tonic-gate 	 * setup the task file registers
19960Sstevel@tonic-gate 	 */
19970Sstevel@tonic-gate 
19980Sstevel@tonic-gate 	if (pktp->cp_passthru) {
19990Sstevel@tonic-gate 		switch (((struct dadkio_rwcmd *)(pktp->cp_passthru))->cmd) {
20000Sstevel@tonic-gate 		case DADKIO_RWCMD_READ:
20010Sstevel@tonic-gate 			pktp->ac_cmd = unitp->au_rd_cmd;
20020Sstevel@tonic-gate 			pktp->ac_direction = AT_IN;
20030Sstevel@tonic-gate 			break;
20040Sstevel@tonic-gate 		case DADKIO_RWCMD_WRITE:
20050Sstevel@tonic-gate 			pktp->ac_cmd = unitp->au_wr_cmd;
20060Sstevel@tonic-gate 			pktp->ac_direction = AT_OUT;
20070Sstevel@tonic-gate 			break;
20080Sstevel@tonic-gate 		}
20090Sstevel@tonic-gate 	} else {
20100Sstevel@tonic-gate 		switch (pktp->ac_cdb) {
20110Sstevel@tonic-gate 		case DCMD_READ:
20120Sstevel@tonic-gate 		case DCMD_WRITE:
20130Sstevel@tonic-gate 		case DCMD_RECAL:
20140Sstevel@tonic-gate 		case DCMD_SEEK:
20150Sstevel@tonic-gate 		case DCMD_RDVER:
20160Sstevel@tonic-gate 			switch (pktp->ac_cdb) {
20170Sstevel@tonic-gate 			case DCMD_READ:
20180Sstevel@tonic-gate 				pktp->ac_cmd = unitp->au_rd_cmd;
20190Sstevel@tonic-gate 				pktp->ac_direction = AT_IN;
20200Sstevel@tonic-gate 				break;
20210Sstevel@tonic-gate 			case DCMD_WRITE:
20220Sstevel@tonic-gate 				pktp->ac_cmd = unitp->au_wr_cmd;
20230Sstevel@tonic-gate 				pktp->ac_direction = AT_OUT;
20240Sstevel@tonic-gate 				break;
20250Sstevel@tonic-gate 			case DCMD_RECAL:
20260Sstevel@tonic-gate 				pktp->ac_cmd = ATC_RECAL;
20270Sstevel@tonic-gate 				pktp->ac_direction = AT_NO_DATA;
20280Sstevel@tonic-gate 				break;
20290Sstevel@tonic-gate 			case DCMD_SEEK:
20300Sstevel@tonic-gate 				pktp->ac_cmd = ATC_SEEK;
20310Sstevel@tonic-gate 				pktp->ac_direction = AT_NO_DATA;
20320Sstevel@tonic-gate 				break;
20330Sstevel@tonic-gate 			case DCMD_RDVER:
20340Sstevel@tonic-gate 				pktp->ac_cmd = ATC_RDVER;
20350Sstevel@tonic-gate 				pktp->ac_direction = AT_NO_DATA;
20360Sstevel@tonic-gate 				break;
20370Sstevel@tonic-gate 			}
20380Sstevel@tonic-gate 			break;
20390Sstevel@tonic-gate 		default:
20400Sstevel@tonic-gate 			cmn_err(CE_CONT, "_iosetup: "
2041*7656SSherry.Moore@Sun.COM 			    "unrecognized cmd 0x%x\n",
2042*7656SSherry.Moore@Sun.COM 			    pktp->ac_cdb);
20430Sstevel@tonic-gate 			break;
20440Sstevel@tonic-gate 		}
20450Sstevel@tonic-gate 	}
20460Sstevel@tonic-gate }
20470Sstevel@tonic-gate 
20480Sstevel@tonic-gate 
20490Sstevel@tonic-gate /* ARGSUSED */
20500Sstevel@tonic-gate int
pcata_spinup(ata_soft_t * softp,int slot)20510Sstevel@tonic-gate pcata_spinup(ata_soft_t *softp, int slot)
20520Sstevel@tonic-gate {
20530Sstevel@tonic-gate 
20540Sstevel@tonic-gate 	if (!(CARD_PRESENT_VALID(softp)))
20550Sstevel@tonic-gate 		return (DDI_FAILURE);
20560Sstevel@tonic-gate 
20570Sstevel@tonic-gate 	if (pcata_wait(AT_ALTSTATUS, ATS_DRDY, ATS_BSY, softp))
20580Sstevel@tonic-gate 		return (DDI_FAILURE);
20590Sstevel@tonic-gate 
20600Sstevel@tonic-gate 	pcata_wait_complete(softp);
20610Sstevel@tonic-gate 
20620Sstevel@tonic-gate 	/* spin up the drive */
20630Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_DRVHD, ATDH_DRIVE0);
20640Sstevel@tonic-gate 
20650Sstevel@tonic-gate 	mutex_enter(&softp->hi_mutex);
20660Sstevel@tonic-gate 	softp->intr_pending++;
20670Sstevel@tonic-gate 	csx_Put8(softp->handle, AT_CMD, ATC_IDLE_IMMED);
20680Sstevel@tonic-gate 	mutex_exit(&softp->hi_mutex);
20690Sstevel@tonic-gate 
20700Sstevel@tonic-gate 	if (pcata_wait(AT_ALTSTATUS,
20710Sstevel@tonic-gate 	    (ATS_DRDY | ATS_DSC), (ATS_BSY | ATS_ERR), softp)) {
20720Sstevel@tonic-gate #ifdef	ATA_DEBUG
20730Sstevel@tonic-gate 		cmn_err(CE_NOTE, "TIMEOUT SPINNING UP: ");
20740Sstevel@tonic-gate 		pcata_print_sttflag(csx_Get8(softp->handle, AT_ALTSTATUS));
20750Sstevel@tonic-gate #endif
20760Sstevel@tonic-gate 		return (DDI_FAILURE);
20770Sstevel@tonic-gate 	}
20780Sstevel@tonic-gate 
20790Sstevel@tonic-gate 	pcata_wait_complete(softp);
20800Sstevel@tonic-gate 
20810Sstevel@tonic-gate 	/* set the R/W multiple value decided at first init  time */
20820Sstevel@tonic-gate 
20830Sstevel@tonic-gate 	PCIDE_OUTB(softp->handle, AT_COUNT, softp->ab_block_factor[0]);
20840Sstevel@tonic-gate 
20850Sstevel@tonic-gate 	mutex_enter(&softp->hi_mutex);
20860Sstevel@tonic-gate 	softp->intr_pending++;
20870Sstevel@tonic-gate 	csx_Put8(softp->handle, AT_CMD, ATC_SETMULT);
20880Sstevel@tonic-gate 	mutex_exit(&softp->hi_mutex);
20890Sstevel@tonic-gate 
20900Sstevel@tonic-gate 	if (pcata_wait(AT_STATUS, 0, ATS_BSY, softp)) {
20910Sstevel@tonic-gate 		/*
20920Sstevel@tonic-gate 		 * there should have been a drive here but it
20930Sstevel@tonic-gate 		 * didn't respond properly. It stayed BUSY.
20940Sstevel@tonic-gate 		 */
20950Sstevel@tonic-gate #ifdef	ATA_DEBUG
20960Sstevel@tonic-gate 		cmn_err(CE_NOTE, "Error Spinning up ATA drive (after CPR)\n");
20970Sstevel@tonic-gate #endif
20980Sstevel@tonic-gate 		return (DDI_FAILURE);
20990Sstevel@tonic-gate 	}
21000Sstevel@tonic-gate 
21010Sstevel@tonic-gate 	return (DDI_SUCCESS);
21020Sstevel@tonic-gate }
21030Sstevel@tonic-gate 
21040Sstevel@tonic-gate #ifdef  ATA_DEBUG
21050Sstevel@tonic-gate static char	*
21060Sstevel@tonic-gate ata_sttvals[] = { "err", "idx", "corr", "drq", "dsc", "dwf", "drdy", "bsy" };
21070Sstevel@tonic-gate 
21080Sstevel@tonic-gate 
21090Sstevel@tonic-gate static void
pcata_print_sttflag(int svalue)21100Sstevel@tonic-gate pcata_print_sttflag(int svalue)
21110Sstevel@tonic-gate {
21120Sstevel@tonic-gate 	int	i;
21130Sstevel@tonic-gate 	char	buf[80];
21140Sstevel@tonic-gate 
21150Sstevel@tonic-gate 	(void) sprintf(buf, "_sttflag = 0x%x [ ", svalue);
21160Sstevel@tonic-gate 
21170Sstevel@tonic-gate 	for (i = 7; i >= 0; i--,  svalue <<= 1) {
21180Sstevel@tonic-gate 		if (svalue & 0x80) {
21190Sstevel@tonic-gate 			(void) strcat(buf, ata_sttvals[i]);
21200Sstevel@tonic-gate 			(void) strcat(buf, " ");
21210Sstevel@tonic-gate 		}
21220Sstevel@tonic-gate 	}
21230Sstevel@tonic-gate 	cmn_err(CE_CONT, "%s ]\n", buf);
21240Sstevel@tonic-gate }
21250Sstevel@tonic-gate #endif
2126