1507c3241Smlf /*
2507c3241Smlf  * CDDL HEADER START
3507c3241Smlf  *
4507c3241Smlf  * The contents of this file are subject to the terms of the
54d27faddSmarx  * Common Development and Distribution License (the "License").
6507c3241Smlf  * You may not use this file except in compliance with the License.
7507c3241Smlf  *
8507c3241Smlf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9507c3241Smlf  * or http://www.opensolaris.org/os/licensing.
10507c3241Smlf  * See the License for the specific language governing permissions
11507c3241Smlf  * and limitations under the License.
12507c3241Smlf  *
13507c3241Smlf  * When distributing Covered Code, include this CDDL HEADER in each
14507c3241Smlf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15507c3241Smlf  * If applicable, add the following below this CDDL HEADER, with the
16507c3241Smlf  * fields enclosed by brackets "[]" replaced with your own identifying
17507c3241Smlf  * information: Portions Copyright [yyyy] [name of copyright owner]
18507c3241Smlf  *
19507c3241Smlf  * CDDL HEADER END
20507c3241Smlf  */
21507c3241Smlf 
22507c3241Smlf /*
233a7782feSxun ni - Sun Microsystems - Beijing China  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24507c3241Smlf  * Use is subject to license terms.
25507c3241Smlf  */
26507c3241Smlf 
27507c3241Smlf #include <sys/types.h>
28507c3241Smlf #include <sys/dkio.h>
29507c3241Smlf #include <sys/cdio.h>
30507c3241Smlf #include <sys/file.h>
31507c3241Smlf 
32507c3241Smlf #include "ata_common.h"
33507c3241Smlf #include "ata_disk.h"
34507c3241Smlf 
35507c3241Smlf /*
36507c3241Smlf  * this typedef really should be in dktp/cmpkt.h
37507c3241Smlf  */
38507c3241Smlf typedef struct cmpkt cmpkt_t;
39507c3241Smlf 
40507c3241Smlf 
41507c3241Smlf /*
42507c3241Smlf  * DADA entry points
43507c3241Smlf  */
44507c3241Smlf 
45507c3241Smlf static int ata_disk_abort(opaque_t ctl_data, cmpkt_t *pktp);
46507c3241Smlf static int ata_disk_reset(opaque_t ctl_data, int level);
47507c3241Smlf static int ata_disk_ioctl(opaque_t ctl_data, int cmd, intptr_t a, int flag);
48507c3241Smlf static cmpkt_t *ata_disk_pktalloc(opaque_t ctl_data, int (*callback)(caddr_t),
49507c3241Smlf     caddr_t arg);
50507c3241Smlf static void ata_disk_pktfree(opaque_t ctl_data, cmpkt_t *pktp);
51507c3241Smlf static cmpkt_t	*ata_disk_memsetup(opaque_t ctl_data, cmpkt_t *pktp,
52507c3241Smlf     struct buf *bp, int (*callback)(caddr_t), caddr_t arg);
53507c3241Smlf static void ata_disk_memfree(opaque_t ctl_data, cmpkt_t *pktp);
54507c3241Smlf static cmpkt_t	*ata_disk_iosetup(opaque_t ctl_data, cmpkt_t *pktp);
55507c3241Smlf static int ata_disk_transport(opaque_t ctl_data, cmpkt_t *pktp);
56507c3241Smlf 
57507c3241Smlf /*
58507c3241Smlf  * DADA packet callbacks
59507c3241Smlf  */
60507c3241Smlf 
61507c3241Smlf static void ata_disk_complete(ata_drv_t *ata_drvp, ata_pkt_t *ata_pktp,
62507c3241Smlf     int do_callback);
63507c3241Smlf static int ata_disk_intr(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
64507c3241Smlf     ata_pkt_t *ata_pktp);
65507c3241Smlf static int ata_disk_intr_dma(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
66507c3241Smlf     ata_pkt_t *ata_pktp);
67507c3241Smlf static int ata_disk_intr_pio_in(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
68507c3241Smlf     ata_pkt_t *ata_pktp);
69507c3241Smlf static int ata_disk_intr_pio_out(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
70507c3241Smlf     ata_pkt_t *ata_pktp);
71507c3241Smlf static int ata_disk_start(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
72507c3241Smlf     ata_pkt_t *ata_pktp);
73507c3241Smlf static int ata_disk_start_dma_in(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
74507c3241Smlf     ata_pkt_t *ata_pktp);
75507c3241Smlf static int ata_disk_start_dma_out(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
76507c3241Smlf     ata_pkt_t *ata_pktp);
77507c3241Smlf static int ata_disk_start_pio_in(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
78507c3241Smlf     ata_pkt_t *ata_pktp);
79507c3241Smlf static int ata_disk_start_pio_out(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
80507c3241Smlf     ata_pkt_t *ata_pktp);
81507c3241Smlf 
82507c3241Smlf /*
83507c3241Smlf  * Local Function prototypes
84507c3241Smlf  */
85507c3241Smlf 
86507c3241Smlf static int ata_disk_eject(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
87507c3241Smlf     ata_pkt_t *ata_pktp);
88507c3241Smlf static void ata_disk_fake_inquiry(ata_drv_t *ata_drvp);
89507c3241Smlf static void ata_disk_get_resid(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
90507c3241Smlf     ata_pkt_t *ata_pktp);
91507c3241Smlf static int ata_disk_initialize_device_parameters(ata_ctl_t *ata_ctlp,
92507c3241Smlf     ata_drv_t *ata_drvp);
93507c3241Smlf static int ata_disk_lock(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
94507c3241Smlf     ata_pkt_t *ata_pktp);
95507c3241Smlf static int ata_disk_set_multiple(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp);
96507c3241Smlf static void ata_disk_pio_xfer_data_in(ata_ctl_t *ata_ctlp, ata_pkt_t *ata_pktp);
97507c3241Smlf static void ata_disk_pio_xfer_data_out(ata_ctl_t *ata_ctlp,
98507c3241Smlf     ata_pkt_t *ata_pktp);
99507c3241Smlf static void ata_disk_set_standby_timer(ata_ctl_t *ata_ctlp,
100507c3241Smlf     ata_drv_t *ata_drvp);
101507c3241Smlf static int ata_disk_recalibrate(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
102507c3241Smlf     ata_pkt_t *ata_pktp);
103507c3241Smlf static int ata_disk_standby(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
104507c3241Smlf     ata_pkt_t *ata_pktp);
105507c3241Smlf static int ata_disk_start_common(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
106507c3241Smlf     ata_pkt_t *ata_pktp);
107507c3241Smlf static int ata_disk_state(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
108507c3241Smlf     ata_pkt_t *ata_pktp);
109507c3241Smlf static int ata_disk_unlock(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
110507c3241Smlf     ata_pkt_t *ata_pktp);
111507c3241Smlf static int ata_get_capacity(ata_drv_t *ata_drvp, uint64_t *capacity);
112507c3241Smlf static void ata_fix_large_disk_geometry(ata_drv_t *ata_drvp);
113507c3241Smlf static uint64_t	ata_calculate_28bits_capacity(ata_drv_t *ata_drvp);
114507c3241Smlf static uint64_t	ata_calculate_48bits_capacity(ata_drv_t *ata_drvp);
115507c3241Smlf static int ata_copy_dk_ioc_string(intptr_t arg, char *source, int length,
116507c3241Smlf     int flag);
117507c3241Smlf static void ata_set_write_cache(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp);
1180f2c99a4Syt static int ata_disk_update_fw(gtgt_t *gtgtp, ata_ctl_t *ata_ctlp,
1190f2c99a4Syt     ata_drv_t *ata_drvp, caddr_t fwfile, uint_t size,
1200f2c99a4Syt     uint8_t type, int flag);
1210f2c99a4Syt static int ata_disk_set_feature_spinup(ata_ctl_t *ata_ctlp,
1220f2c99a4Syt     ata_drv_t *ata_drvp, ata_pkt_t *ata_pktp);
1230f2c99a4Syt static int ata_disk_id_update(ata_ctl_t *ata_ctlp,
1240f2c99a4Syt     ata_drv_t *ata_drvp, ata_pkt_t *ata_pktp);
125507c3241Smlf 
126507c3241Smlf 
127507c3241Smlf /*
128507c3241Smlf  * Local static data
129507c3241Smlf  */
130507c3241Smlf 
131507c3241Smlf uint_t	ata_disk_init_dev_parm_wait = 4 * 1000000;
132507c3241Smlf uint_t	ata_disk_set_mult_wait = 4 * 1000000;
133507c3241Smlf int	ata_disk_do_standby_timer = TRUE;
134507c3241Smlf 
1350f2c99a4Syt /* timeout value for device update firmware */
1360f2c99a4Syt int	ata_disk_updatefw_time = 60;
1370f2c99a4Syt 
138507c3241Smlf /*
139507c3241Smlf  * ata_write_cache == 1  force write cache on.
140507c3241Smlf  * ata_write_cache == 0  do not modify write cache.  firmware defaults kept.
141507c3241Smlf  * ata_write_cache == -1 force write cache off.
142507c3241Smlf  */
143507c3241Smlf int	ata_write_cache = 1;
144507c3241Smlf 
145507c3241Smlf 
146507c3241Smlf static struct ctl_objops ata_disk_objops = {
147507c3241Smlf 	ata_disk_pktalloc,
148507c3241Smlf 	ata_disk_pktfree,
149507c3241Smlf 	ata_disk_memsetup,
150507c3241Smlf 	ata_disk_memfree,
151507c3241Smlf 	ata_disk_iosetup,
152507c3241Smlf 	ata_disk_transport,
153507c3241Smlf 	ata_disk_reset,
154507c3241Smlf 	ata_disk_abort,
155507c3241Smlf 	nulldev,
156507c3241Smlf 	nulldev,
157507c3241Smlf 	ata_disk_ioctl,
158507c3241Smlf 	0, 0
159507c3241Smlf };
160507c3241Smlf 
161507c3241Smlf 
162507c3241Smlf 
163507c3241Smlf /*
164507c3241Smlf  *
165507c3241Smlf  * initialize the ata_disk sub-system
166507c3241Smlf  *
167507c3241Smlf  */
168507c3241Smlf 
169507c3241Smlf /*ARGSUSED*/
170507c3241Smlf int
ata_disk_attach(ata_ctl_t * ata_ctlp)171507c3241Smlf ata_disk_attach(
172507c3241Smlf 	ata_ctl_t *ata_ctlp)
173507c3241Smlf {
174507c3241Smlf 	ADBG_TRACE(("ata_disk_init entered\n"));
175507c3241Smlf 	return (TRUE);
176507c3241Smlf }
177507c3241Smlf 
178507c3241Smlf 
179507c3241Smlf 
180507c3241Smlf /*
181507c3241Smlf  *
182507c3241Smlf  * destroy the ata_disk sub-system
183507c3241Smlf  *
184507c3241Smlf  */
185507c3241Smlf 
186507c3241Smlf /*ARGSUSED*/
187507c3241Smlf void
ata_disk_detach(ata_ctl_t * ata_ctlp)188507c3241Smlf ata_disk_detach(
189507c3241Smlf 	ata_ctl_t *ata_ctlp)
190507c3241Smlf {
191507c3241Smlf 	ADBG_TRACE(("ata_disk_destroy entered\n"));
192507c3241Smlf }
193507c3241Smlf 
194507c3241Smlf 
195507c3241Smlf /*
196507c3241Smlf  * Test whether the disk can support Logical Block Addressing
197507c3241Smlf  */
198507c3241Smlf 
199507c3241Smlf int
ata_test_lba_support(struct ata_id * aidp)200507c3241Smlf ata_test_lba_support(struct ata_id *aidp)
201507c3241Smlf {
202507c3241Smlf #ifdef __old_version__
203507c3241Smlf 	/*
204507c3241Smlf 	 * determine if the drive supports LBA mode
205507c3241Smlf 	 */
206507c3241Smlf 	if (aidp->ai_cap & ATAC_LBA_SUPPORT)
207507c3241Smlf 		return (TRUE);
208507c3241Smlf #else
209507c3241Smlf 	/*
210507c3241Smlf 	 * Determine if the drive supports LBA mode
211507c3241Smlf 	 * LBA mode is mandatory on ATA-3 (or newer) drives but is
212507c3241Smlf 	 * optional on ATA-2 (or older) drives. On ATA-2 drives
213507c3241Smlf 	 * the ai_majorversion word should be 0xffff or 0x0000
214507c3241Smlf 	 * (version not reported).
215507c3241Smlf 	 */
216507c3241Smlf 	if (aidp->ai_majorversion != 0xffff &&
217507c3241Smlf 	    aidp->ai_majorversion >= (1 << 3)) {
218507c3241Smlf 		/* ATA-3 or better */
219507c3241Smlf 		return (TRUE);
220507c3241Smlf 	} else if (aidp->ai_cap & ATAC_LBA_SUPPORT) {
221507c3241Smlf 		/* ATA-2 LBA capability bit set */
222507c3241Smlf 		return (TRUE);
223507c3241Smlf 	} else {
224507c3241Smlf 		return (FALSE);
225507c3241Smlf 	}
226507c3241Smlf #endif
227507c3241Smlf }
228507c3241Smlf 
229507c3241Smlf /*
230507c3241Smlf  * ATA-6 drives do not provide geometry information, so words
231507c3241Smlf  * ai_heads, ai_sectors and ai_fixcyls may not be valid
232507c3241Smlf  */
233507c3241Smlf static void
ata_fixup_ata6_geometry(struct ata_id * aidp)234507c3241Smlf ata_fixup_ata6_geometry(struct ata_id *aidp)
235507c3241Smlf {
236507c3241Smlf 	/* check cylinders, heads, and sectors for valid values */
237507c3241Smlf 	if (aidp->ai_heads != 0 && aidp->ai_heads != 0xffff &&
238507c3241Smlf 	    aidp->ai_sectors != 0 && aidp->ai_sectors != 0xffff &&
239507c3241Smlf 	    aidp->ai_fixcyls != 0)
240507c3241Smlf 		return;		/* assume valid geometry - do nothing */
241507c3241Smlf 
242507c3241Smlf 	/*
243507c3241Smlf 	 * Pre-set standard geometry values - they are not necessarily
244507c3241Smlf 	 * optimal for a given capacity
245507c3241Smlf 	 */
246507c3241Smlf 	aidp->ai_heads = 0x10;
247507c3241Smlf 	aidp->ai_sectors = 0x3f;
248507c3241Smlf 	aidp->ai_fixcyls = 1;
249507c3241Smlf 	/*
250507c3241Smlf 	 * The fixcyls value will get fixed up later in
251507c3241Smlf 	 * ata_fix_large_disk_geometry.
252507c3241Smlf 	 */
253507c3241Smlf }
254507c3241Smlf 
255507c3241Smlf /*
256507c3241Smlf  *
257507c3241Smlf  * initialize the soft-structure for an ATA (non-PACKET) drive and
258507c3241Smlf  * then configure the drive with the correct modes and options.
259507c3241Smlf  *
260507c3241Smlf  */
261507c3241Smlf 
262507c3241Smlf int
ata_disk_init_drive(ata_drv_t * ata_drvp)263507c3241Smlf ata_disk_init_drive(
264507c3241Smlf 	ata_drv_t *ata_drvp)
265507c3241Smlf {
266507c3241Smlf 	ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
267507c3241Smlf 	struct ata_id	*aidp = &ata_drvp->ad_id;
268507c3241Smlf 	struct ctl_obj	*ctlobjp;
269507c3241Smlf 	struct scsi_device	*devp;
270*1bff1300SToomas Soome 	int		len;
271507c3241Smlf 	int		val;
272507c3241Smlf 	int		mode;
273507c3241Smlf 	short		*chs;
274*1bff1300SToomas Soome 	char		buf[80];
275507c3241Smlf 
276507c3241Smlf 	ADBG_TRACE(("ata_disk_init_drive entered\n"));
277507c3241Smlf 
278507c3241Smlf 	/* ATA disks don't support LUNs */
279507c3241Smlf 
280507c3241Smlf 	if (ata_drvp->ad_lun != 0)
281507c3241Smlf 		return (FALSE);
282507c3241Smlf 
283507c3241Smlf 	/*
284507c3241Smlf 	 * set up drive structure
285507c3241Smlf 	 * ATA-6 drives do not provide geometry information, so words
286507c3241Smlf 	 * ai_heads, ai_sectors and ai_fixcyls may not be valid - they
287507c3241Smlf 	 * will be fixed later
288507c3241Smlf 	 */
289507c3241Smlf 
290507c3241Smlf 	ata_drvp->ad_phhd = aidp->ai_heads;
291507c3241Smlf 	ata_drvp->ad_phsec = aidp->ai_sectors;
292507c3241Smlf 	ata_drvp->ad_drvrhd   = aidp->ai_heads;
293507c3241Smlf 	ata_drvp->ad_drvrsec  = aidp->ai_sectors;
294507c3241Smlf 	ata_drvp->ad_drvrcyl  = aidp->ai_fixcyls;
295507c3241Smlf 	ata_drvp->ad_acyl = 0;
296507c3241Smlf 
297507c3241Smlf 	if (ata_test_lba_support(&ata_drvp->ad_id))
298507c3241Smlf 		ata_drvp->ad_drive_bits |= ATDH_LBA;
299507c3241Smlf 
300507c3241Smlf 	/* Get capacity and check for 48-bit mode */
301507c3241Smlf 	mode = ata_get_capacity(ata_drvp, &ata_drvp->ad_capacity);
302507c3241Smlf 	if (mode == AD_EXT48) {
303507c3241Smlf 		ata_drvp->ad_flags |= AD_EXT48;
304507c3241Smlf 	}
305507c3241Smlf 
306507c3241Smlf 	/* straighten out the geometry */
307507c3241Smlf 	(void) sprintf(buf, "SUNW-ata-%p-d%d-chs", (void *) ata_ctlp->ac_data,
308*1bff1300SToomas Soome 	    ata_drvp->ad_targ+1);
309507c3241Smlf 	if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_root_node(), 0,
310*1bff1300SToomas Soome 	    buf, (caddr_t)&chs, &len) == DDI_PROP_SUCCESS) {
311507c3241Smlf 		/*
312507c3241Smlf 		 * if the number of sectors and heads in bios matches the
313507c3241Smlf 		 * physical geometry, then so should the number of cylinders
314507c3241Smlf 		 * this is to prevent the 1023 limit in the older bios's
315507c3241Smlf 		 * causing loss of space.
316507c3241Smlf 		 */
317507c3241Smlf 		if (chs[1] == (ata_drvp->ad_drvrhd - 1) &&
318*1bff1300SToomas Soome 		    chs[2] == ata_drvp->ad_drvrsec) {
319507c3241Smlf 			/* Set chs[0] to zero-based number of cylinders. */
320507c3241Smlf 			chs[0] = aidp->ai_fixcyls - 1;
321*1bff1300SToomas Soome 		} else if (!(ata_drvp->ad_drive_bits & ATDH_LBA)) {
322507c3241Smlf 			/*
323507c3241Smlf 			 * if the the sector/heads do not match that of the
324507c3241Smlf 			 * bios and the drive does not support LBA. We go ahead
325507c3241Smlf 			 * and advertise the bios geometry but use the physical
326507c3241Smlf 			 * geometry for sector translation.
327507c3241Smlf 			 */
328507c3241Smlf 			cmn_err(CE_WARN, "!Disk 0x%p,%d: BIOS geometry "
329*1bff1300SToomas Soome 			    "different from physical, and no LBA support.",
330*1bff1300SToomas Soome 			    (void *)ata_ctlp->ac_data, ata_drvp->ad_targ);
331507c3241Smlf 		}
332507c3241Smlf 
333507c3241Smlf 		/*
334507c3241Smlf 		 * chs[0,1] are zero-based; make them one-based.
335507c3241Smlf 		 */
336507c3241Smlf 		ata_drvp->ad_drvrcyl = chs[0] + 1;
337507c3241Smlf 		ata_drvp->ad_drvrhd = chs[1] + 1;
338507c3241Smlf 		ata_drvp->ad_drvrsec = chs[2];
339507c3241Smlf 		kmem_free(chs, len);
340507c3241Smlf 	} else {
341507c3241Smlf 		/*
342507c3241Smlf 		 * Property not present; this means that boot.bin has
343507c3241Smlf 		 * determined that the drive supports Int13 LBA.  Note
344507c3241Smlf 		 * this, but just return a geometry with a large
345507c3241Smlf 		 * cylinder count; this will be the signal for dadk to
346507c3241Smlf 		 * fail DKIOCG_VIRTGEOM.
347507c3241Smlf 		 * ad_drvr* are already set; just recalculate ad_drvrcyl
348507c3241Smlf 		 * from capacity.
349507c3241Smlf 		 */
350507c3241Smlf 
351507c3241Smlf 		ata_drvp->ad_flags |= AD_INT13LBA;
352507c3241Smlf 		if (ata_drvp->ad_capacity != 0) {
353507c3241Smlf 			ata_drvp->ad_drvrcyl = ata_drvp->ad_capacity /
354*1bff1300SToomas Soome 			    (ata_drvp->ad_drvrhd * ata_drvp->ad_drvrsec);
355507c3241Smlf 		} else {
356507c3241Smlf 			/*
357507c3241Smlf 			 * Something's wrong; return something sure to
358507c3241Smlf 			 * fail the "cyls < 1024" test.  This will
359507c3241Smlf 			 * never make it out of the DKIOCG_VIRTGEOM
360507c3241Smlf 			 * call, so its total bogosity won't matter.
361507c3241Smlf 			 */
362507c3241Smlf 			ata_drvp->ad_drvrcyl = 1025;
363507c3241Smlf 			ata_drvp->ad_drvrhd = 1;
364507c3241Smlf 			ata_drvp->ad_drvrsec = 1;
365507c3241Smlf 		}
366507c3241Smlf 	}
367507c3241Smlf 
368507c3241Smlf 	/* fix geometry for disks > 31GB, if needed */
369507c3241Smlf 	ata_fix_large_disk_geometry(ata_drvp);
370507c3241Smlf 
371507c3241Smlf 	/*
372507c3241Smlf 	 * set up the scsi_device and ctl_obj structures
373507c3241Smlf 	 */
374602ca9eaScth 	devp = kmem_zalloc(scsi_device_size(), KM_SLEEP);
375602ca9eaScth 	ata_drvp->ad_device = devp;
376507c3241Smlf 	ctlobjp = &ata_drvp->ad_ctl_obj;
377507c3241Smlf 
378507c3241Smlf 	devp->sd_inq = &ata_drvp->ad_inquiry;
379507c3241Smlf 	devp->sd_address.a_hba_tran = (scsi_hba_tran_t *)ctlobjp;
380507c3241Smlf 	devp->sd_address.a_target = (ushort_t)ata_drvp->ad_targ;
381507c3241Smlf 	devp->sd_address.a_lun = (uchar_t)ata_drvp->ad_lun;
382507c3241Smlf 	mutex_init(&devp->sd_mutex, NULL, MUTEX_DRIVER, NULL);
383507c3241Smlf 	ata_drvp->ad_flags |= AD_MUTEX_INIT;
384507c3241Smlf 
385507c3241Smlf 	/*
386507c3241Smlf 	 * DADA ops vectors and cookie
387507c3241Smlf 	 */
388507c3241Smlf 	ctlobjp->c_ops  = (struct ctl_objops *)&ata_disk_objops;
389507c3241Smlf 
390507c3241Smlf 	/*
391507c3241Smlf 	 * this is filled in with gtgtp by ata_disk_bus_ctl(INITCHILD)
392507c3241Smlf 	 */
393507c3241Smlf 	ctlobjp->c_data = NULL;
394507c3241Smlf 
395507c3241Smlf 	ctlobjp->c_ext  = &(ctlobjp->c_extblk);
396507c3241Smlf 	ctlobjp->c_extblk.c_ctldip = ata_ctlp->ac_dip;
397507c3241Smlf 	ctlobjp->c_extblk.c_targ   = ata_drvp->ad_targ;
398507c3241Smlf 	ctlobjp->c_extblk.c_blksz  = NBPSCTR;
399507c3241Smlf 
400507c3241Smlf 	/*
401507c3241Smlf 	 * Get highest block factor supported by the drive.
402507c3241Smlf 	 * Some drives report 0 if read/write multiple not supported,
403507c3241Smlf 	 * adjust their blocking factor to 1.
404507c3241Smlf 	 */
405507c3241Smlf 	ata_drvp->ad_block_factor = aidp->ai_mult1 & 0xff;
406507c3241Smlf 
407507c3241Smlf 	/*
408507c3241Smlf 	 * If a block factor property exists, use the smaller of the
409507c3241Smlf 	 * property value and the highest value the drive can support.
410507c3241Smlf 	 */
411507c3241Smlf 	(void) sprintf(buf, "drive%d_block_factor", ata_drvp->ad_targ);
412507c3241Smlf 	val = ddi_prop_get_int(DDI_DEV_T_ANY, ata_ctlp->ac_dip, 0, buf,
413*1bff1300SToomas Soome 	    ata_drvp->ad_block_factor);
414507c3241Smlf 
415507c3241Smlf 	ata_drvp->ad_block_factor = (short)min(val, ata_drvp->ad_block_factor);
416507c3241Smlf 
417507c3241Smlf 	if (ata_drvp->ad_block_factor == 0)
418507c3241Smlf 		ata_drvp->ad_block_factor = 1;
419507c3241Smlf 
420602ca9eaScth 	if (!ata_disk_setup_parms(ata_ctlp, ata_drvp)) {
421602ca9eaScth 		ata_drvp->ad_device = NULL;
422602ca9eaScth 		kmem_free(devp, scsi_device_size());
423507c3241Smlf 		return (FALSE);
424602ca9eaScth 	}
425507c3241Smlf 
426507c3241Smlf 	ata_disk_fake_inquiry(ata_drvp);
427507c3241Smlf 
428507c3241Smlf 	return (TRUE);
429507c3241Smlf }
430507c3241Smlf 
431507c3241Smlf /*
432507c3241Smlf  * Test if a disk supports 48-bit (extended mode) addressing and
433507c3241Smlf  * get disk capacity.
434507c3241Smlf  * Return value:
435507c3241Smlf  *	AD_EXT48 if 48-bit mode is available, 0 otherwise,
436507c3241Smlf  *	capacity in sectors.
437507c3241Smlf  * There are several indicators for 48-bit addressing.  If any of
438507c3241Smlf  * them is missing, assume 28-bit (non-extended) addressing.
439507c3241Smlf  */
440507c3241Smlf 
441507c3241Smlf static int
ata_get_capacity(ata_drv_t * ata_drvp,uint64_t * capacity)442507c3241Smlf ata_get_capacity(ata_drv_t *ata_drvp, uint64_t *capacity)
443507c3241Smlf {
444507c3241Smlf 	struct ata_id	*aidp = &ata_drvp->ad_id;
445507c3241Smlf 	uint64_t	cap28;	/* capacity in 28-bit mode */
446507c3241Smlf 	uint64_t	cap48;	/* capacity in 48-bit mode */
447507c3241Smlf 
448507c3241Smlf 	/*
449507c3241Smlf 	 * First compute capacity in 28-bit mode, using 28-bit capacity
450507c3241Smlf 	 * words in IDENTIFY DEVICE response words
451507c3241Smlf 	 */
452507c3241Smlf 	cap28 = ata_calculate_28bits_capacity(ata_drvp);
453507c3241Smlf 	*capacity = cap28;
454507c3241Smlf 
4558c112d45SColin Yi 	if (!IS_ATA_VERSION_SUPPORTED(aidp, 6) &&
4568c112d45SColin Yi 	    !(ata_drvp->ad_flags & AD_BLLBA48))
457507c3241Smlf 		return (0);
458507c3241Smlf 
459507c3241Smlf 	/* Check that 48 bit addressing is supported & enabled */
460507c3241Smlf 	/* words 83 and 86 */
461507c3241Smlf 	if (!(aidp->ai_cmdset83 & ATACS_EXT48))
462507c3241Smlf 		return (0);
463507c3241Smlf 	if (!(aidp->ai_features86 & ATACS_EXT48))
464507c3241Smlf 		return (0);
465507c3241Smlf 
466507c3241Smlf 	/*
467507c3241Smlf 	 * Drive supports ATA-6.  Since ATA-6 drives may not provide
468507c3241Smlf 	 * geometry info, pre-set standard geometry values
469507c3241Smlf 	 */
470507c3241Smlf 	ata_fixup_ata6_geometry(aidp);
471507c3241Smlf 
472507c3241Smlf 	/* Compute 48-bit capacity */
473507c3241Smlf 	cap48 = ata_calculate_48bits_capacity(ata_drvp);
474507c3241Smlf 
475507c3241Smlf 	/*
476507c3241Smlf 	 * If capacity is smaller then the maximum capacity addressable
477507c3241Smlf 	 * in 28-bit mode, just use 28-bit capacity value.
478507c3241Smlf 	 * We will use 28-bit addressing read/write commands.
479507c3241Smlf 	 */
480507c3241Smlf 	if (cap48 <= MAX_28BIT_CAPACITY)
481507c3241Smlf 		return (0);
482507c3241Smlf 
483507c3241Smlf 	/*
484507c3241Smlf 	 * Capacity is too big for 28-bits addressing. But, to make
485507c3241Smlf 	 * sure that the drive implements ATA-6 correctly, the
486507c3241Smlf 	 * final check: cap28 should be MAX for 28-bit addressing.
487507c3241Smlf 	 * If it's not, we shouldn't use 48-bit mode, so return
488507c3241Smlf 	 * the capacity reported in 28-bit capacity words.
489507c3241Smlf 	 */
490507c3241Smlf 	if (cap28 != MAX_28BIT_CAPACITY)
491507c3241Smlf 		return (0);		/* not max, use 28-bit value */
492507c3241Smlf 
493507c3241Smlf 	/*
494507c3241Smlf 	 * All is well so return 48-bit capacity indicator
495507c3241Smlf 	 */
496507c3241Smlf 	ADBG_INIT(("ATA: using 48-bit mode for capacity %llx blocks\n",
497*1bff1300SToomas Soome 	    (unsigned long long)cap48));
498507c3241Smlf 
499507c3241Smlf 	*capacity = cap48;
500507c3241Smlf 	return (AD_EXT48);
501507c3241Smlf }
502507c3241Smlf 
503507c3241Smlf /*
504507c3241Smlf  * With the advent of disks that hold more than 31 GB, we run into a
505507c3241Smlf  * limitation in the sizes of the fields that describe the geometry.
506507c3241Smlf  * The cylinders, heads, and sectors-per-track are each described by a
507507c3241Smlf  * 16-bit number -- both in the structure returned from IDENTIFY
508507c3241Smlf  * DEVICE and in the structure returned from the DIOCTL_GETGEOM or
509507c3241Smlf  * DIOCTL_GETPHYGEOM ioctl.
510507c3241Smlf  *
511507c3241Smlf  * The typical disk has 32 heads per cylinder and 63 sectors per
512507c3241Smlf  * track.  A 16 bit field can contain up to 65535.  So the largest
513507c3241Smlf  * disk that can be described in these fields is 65535 * 32 * 63 * 512
514507c3241Smlf  * (bytes/sector), or about 31.5 GB.  The cylinder count gets truncated
515507c3241Smlf  * when stored in a narrow field, so a 40GB disk appears to have only
516507c3241Smlf  * 8 GB!
517507c3241Smlf  *
518507c3241Smlf  * The solution (for the time being at least) is to lie about the
519507c3241Smlf  * geometry.  If the number of cylinders is too large to fit in 16
520507c3241Smlf  * bits, we will halve the cylinders and double the heads, repeating
521507c3241Smlf  * until we can fit the geometry into 3 shorts.
522507c3241Smlf  * FUTURE ENHANCEMENT: If this ever isn't enough, we could
523507c3241Smlf  * add another step to double sectors/track as well.
524507c3241Smlf  */
525507c3241Smlf 
526507c3241Smlf static void
ata_fix_large_disk_geometry(ata_drv_t * ata_drvp)527507c3241Smlf ata_fix_large_disk_geometry(
528507c3241Smlf 	ata_drv_t *ata_drvp)
529507c3241Smlf {
530507c3241Smlf 	struct ata_id	*aidp = &ata_drvp->ad_id;
531507c3241Smlf 
532507c3241Smlf 	/* no hope for large disks if LBA not supported */
533507c3241Smlf 	if (!(ata_drvp->ad_drive_bits & ATDH_LBA))
534507c3241Smlf 		return;
535507c3241Smlf 
536507c3241Smlf 	/*
537507c3241Smlf 	 * Fix up the geometry to be returned by DIOCTL_GETGEOM.
538507c3241Smlf 	 * If number of cylinders > USHRT_MAX, double heads and
539507c3241Smlf 	 * halve cylinders until everything fits.
540507c3241Smlf 	 */
541507c3241Smlf 	while (ata_drvp->ad_drvrcyl > USHRT_MAX) {
542507c3241Smlf 		int tempheads;
543507c3241Smlf 
544507c3241Smlf 		/* is there room in 16 bits to double the heads? */
545507c3241Smlf 		tempheads = 2 * ata_drvp->ad_drvrhd;
546507c3241Smlf 		if (tempheads > USHRT_MAX) {
547507c3241Smlf 			/*
548507c3241Smlf 			 * No room to double the heads.
549507c3241Smlf 			 * I give up, there's no way to represent this.
550507c3241Smlf 			 * Limit disk size.
551507c3241Smlf 			 */
552*1bff1300SToomas Soome 			cmn_err(CE_WARN, "Disk is too large: "
553*1bff1300SToomas Soome 			    "Model %s, Serial# %s Approximating...\n",
554*1bff1300SToomas Soome 			    aidp->ai_model, aidp->ai_drvser);
555507c3241Smlf 			ata_drvp->ad_drvrcyl = USHRT_MAX;
556507c3241Smlf 			break;
557507c3241Smlf 		}
558507c3241Smlf 
559507c3241Smlf 		/* OK, so double the heads and halve the cylinders */
560507c3241Smlf 		ata_drvp->ad_drvrcyl /= 2;
561507c3241Smlf 		ata_drvp->ad_drvrhd *= 2;
562507c3241Smlf 	}
563507c3241Smlf }
564507c3241Smlf 
565507c3241Smlf /*
566507c3241Smlf  * Calculate capacity using 28-bit capacity words from IDENTIFY DEVICE
567507c3241Smlf  * return words
568507c3241Smlf  */
569507c3241Smlf uint64_t
ata_calculate_28bits_capacity(ata_drv_t * ata_drvp)570507c3241Smlf ata_calculate_28bits_capacity(ata_drv_t *ata_drvp)
571507c3241Smlf {
572507c3241Smlf 	/*
573507c3241Smlf 	 * Asked x3t13 for advice; this implements Hale Landis'
574507c3241Smlf 	 * response, minus the "use ATA_INIT_DEVPARMS".
575507c3241Smlf 	 * See "capacity.notes".
576507c3241Smlf 	 */
577507c3241Smlf 
578507c3241Smlf 	/* some local shorthand/renaming to clarify the meaning */
579507c3241Smlf 
580507c3241Smlf 	ushort_t curcyls_w54, curhds_w55, cursect_w56;
581507c3241Smlf 	uint32_t curcap_w57_58;
582507c3241Smlf 
583507c3241Smlf 	if ((ata_drvp->ad_drive_bits & ATDH_LBA) != 0) {
584507c3241Smlf 		return ((uint64_t)(ata_drvp->ad_id.ai_addrsec[0] +
585507c3241Smlf 		    ata_drvp->ad_id.ai_addrsec[1] * 0x10000));
586507c3241Smlf 	}
587507c3241Smlf 
588507c3241Smlf 	/*
589507c3241Smlf 	 * If we're not LBA, then first try to validate "current" values.
590507c3241Smlf 	 */
591507c3241Smlf 
592507c3241Smlf 	curcyls_w54 = ata_drvp->ad_id.ai_curcyls;
593507c3241Smlf 	curhds_w55 = ata_drvp->ad_id.ai_curheads;
594507c3241Smlf 	cursect_w56 = ata_drvp->ad_id.ai_cursectrk;
595507c3241Smlf 	curcap_w57_58 = ata_drvp->ad_id.ai_cursccp[0] +
596507c3241Smlf 	    ata_drvp->ad_id.ai_cursccp[1] * 0x10000;
597507c3241Smlf 
598507c3241Smlf 	if (((ata_drvp->ad_id.ai_validinfo & 1) == 1) &&
599507c3241Smlf 	    (curhds_w55 >= 1) && (curhds_w55 <= 16) &&
600507c3241Smlf 	    (cursect_w56 >= 1) && (cursect_w56 <= 63) &&
601507c3241Smlf 	    (curcap_w57_58 == curcyls_w54 * curhds_w55 * cursect_w56)) {
602507c3241Smlf 		return ((uint64_t)curcap_w57_58);
603507c3241Smlf 	}
604507c3241Smlf 
605507c3241Smlf 	/*
606507c3241Smlf 	 * At this point, Hale recommends ATA_INIT_DEVPARMS.
607507c3241Smlf 	 * I don't want to do that, so simply use 1/3/6 as
608507c3241Smlf 	 * a final fallback, and continue to assume the BIOS
609507c3241Smlf 	 * has done whatever INIT_DEVPARMS are necessary.
610507c3241Smlf 	 */
611507c3241Smlf 
612507c3241Smlf 	return ((uint64_t)(ata_drvp->ad_id.ai_fixcyls *
613*1bff1300SToomas Soome 	    ata_drvp->ad_id.ai_heads * ata_drvp->ad_id.ai_sectors));
614507c3241Smlf }
615507c3241Smlf 
616507c3241Smlf /*
617507c3241Smlf  * Calculate capacity using 48-bits capacity words from IDENTIFY DEVICE
618507c3241Smlf  * return words
619507c3241Smlf  */
620507c3241Smlf uint64_t
ata_calculate_48bits_capacity(ata_drv_t * ata_drvp)621507c3241Smlf ata_calculate_48bits_capacity(ata_drv_t *ata_drvp)
622507c3241Smlf {
623507c3241Smlf 	uint64_t cap48 = 0;
624507c3241Smlf 	int i;
625507c3241Smlf 
626507c3241Smlf 	for (i = 3;  i >= 0;  --i) {
627507c3241Smlf 		cap48 <<= 16;
628507c3241Smlf 		cap48 += ata_drvp->ad_id.ai_addrsecxt[i];
629507c3241Smlf 	}
630507c3241Smlf 	return (cap48);
631507c3241Smlf }
632507c3241Smlf 
633507c3241Smlf 
634507c3241Smlf /*
635507c3241Smlf  *
636507c3241Smlf  * Setup the drives Read/Write Multiple Blocking factor and the
637507c3241Smlf  * current translation geometry. Necessary during attach and after
638507c3241Smlf  * Software Resets.
639507c3241Smlf  *
640507c3241Smlf  */
641507c3241Smlf 
642507c3241Smlf int
ata_disk_setup_parms(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp)643507c3241Smlf ata_disk_setup_parms(
644507c3241Smlf 	ata_ctl_t *ata_ctlp,
645507c3241Smlf 	ata_drv_t *ata_drvp)
646507c3241Smlf {
647507c3241Smlf 
648507c3241Smlf 	/*
649507c3241Smlf 	 * program geometry info back to the drive
650507c3241Smlf 	 */
651507c3241Smlf 	if (!ata_disk_initialize_device_parameters(ata_ctlp, ata_drvp)) {
652507c3241Smlf 		return (FALSE);
653507c3241Smlf 	}
654507c3241Smlf 
655507c3241Smlf 	/*
656507c3241Smlf 	 * Determine the blocking factor
657507c3241Smlf 	 */
658507c3241Smlf 	if (ata_drvp->ad_block_factor > 1) {
659507c3241Smlf 		/*
660507c3241Smlf 		 * Program the block factor into the drive. If this
661507c3241Smlf 		 * fails, then go back to using a block size of 1.
662507c3241Smlf 		 */
663507c3241Smlf 		if (!ata_disk_set_multiple(ata_ctlp, ata_drvp))
664507c3241Smlf 			ata_drvp->ad_block_factor = 1;
665507c3241Smlf 	}
666507c3241Smlf 
667507c3241Smlf 
668507c3241Smlf 	if (ata_drvp->ad_block_factor > 1) {
669507c3241Smlf 		ata_drvp->ad_rd_cmd = ATC_RDMULT;
670507c3241Smlf 		ata_drvp->ad_wr_cmd = ATC_WRMULT;
671507c3241Smlf 	} else {
672507c3241Smlf 		ata_drvp->ad_rd_cmd = ATC_RDSEC;
673507c3241Smlf 		ata_drvp->ad_wr_cmd = ATC_WRSEC;
674507c3241Smlf 	}
675507c3241Smlf 
676507c3241Smlf 	ata_drvp->ad_bytes_per_block = ata_drvp->ad_block_factor << SCTRSHFT;
677507c3241Smlf 
678507c3241Smlf 	ADBG_INIT(("set block factor for drive %d to %d\n",
679*1bff1300SToomas Soome 	    ata_drvp->ad_targ, ata_drvp->ad_block_factor));
680507c3241Smlf 
681507c3241Smlf 	if (ata_disk_do_standby_timer)
682507c3241Smlf 		ata_disk_set_standby_timer(ata_ctlp, ata_drvp);
683507c3241Smlf 
684507c3241Smlf 	ata_set_write_cache(ata_ctlp, ata_drvp);
685507c3241Smlf 
686507c3241Smlf 	return (TRUE);
687507c3241Smlf }
688507c3241Smlf 
689507c3241Smlf 
690507c3241Smlf /*
691507c3241Smlf  * Take the timeout value specified in the "standby" property
692507c3241Smlf  * and convert from seconds to the magic parm expected by the
693507c3241Smlf  * the drive. Then issue the IDLE command to set the drive's
694507c3241Smlf  * internal standby timer.
695507c3241Smlf  */
696507c3241Smlf 
697507c3241Smlf static void
ata_disk_set_standby_timer(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp)698507c3241Smlf ata_disk_set_standby_timer(
699507c3241Smlf 	ata_ctl_t *ata_ctlp,
700507c3241Smlf 	ata_drv_t *ata_drvp)
701507c3241Smlf {
702507c3241Smlf 	uchar_t	parm;
703507c3241Smlf 	int	timeout = ata_ctlp->ac_standby_time;
704507c3241Smlf 
705507c3241Smlf 	/*
706507c3241Smlf 	 * take the timeout value, specificed in seconds, and
707507c3241Smlf 	 * encode it into the proper command parm
708507c3241Smlf 	 */
709507c3241Smlf 
710507c3241Smlf 	/*
711507c3241Smlf 	 * don't change it if no property specified or if
712507c3241Smlf 	 * the specified value is out of range
713507c3241Smlf 	 */
714507c3241Smlf 	if (timeout < 0 || timeout > (12 * 60 * 60))
715507c3241Smlf 		return;
716507c3241Smlf 
717507c3241Smlf 	/* 1 to 1200 seconds (20 minutes) == N * 5 seconds */
718507c3241Smlf 	if (timeout <= (240 * 5))
719507c3241Smlf 		parm = (timeout + 4) / 5;
720507c3241Smlf 
721507c3241Smlf 	/* 20 to 21 minutes == 21 minutes */
722507c3241Smlf 	else if (timeout <= (21 * 60))
723507c3241Smlf 		parm = 252;
724507c3241Smlf 
725507c3241Smlf 	/* 21 minutes to 21 minutes 15 seconds == 21:15 */
726507c3241Smlf 	else if (timeout <= ((21 * 60) + 15))
727507c3241Smlf 		parm = 255;
728507c3241Smlf 
729507c3241Smlf 	/* 21:15 to 330 minutes == N * 30 minutes */
730507c3241Smlf 	else if (timeout <= (11 * 30 * 60))
731507c3241Smlf 		parm = 240 + ((timeout + (30 * 60) - 1)/ (30 * 60));
732507c3241Smlf 
733507c3241Smlf 	/* > 330 minutes == 8 to 12 hours */
734507c3241Smlf 	else
735507c3241Smlf 		parm = 253;
736507c3241Smlf 
737507c3241Smlf 	(void) ata_command(ata_ctlp, ata_drvp, TRUE, FALSE, 5 * 1000000,
738*1bff1300SToomas Soome 	    ATC_IDLE, 0, parm, 0, 0, 0, 0);
739507c3241Smlf }
740507c3241Smlf 
741507c3241Smlf 
742507c3241Smlf 
743507c3241Smlf /*
744507c3241Smlf  *
745507c3241Smlf  * destroy an ata disk drive
746507c3241Smlf  *
747507c3241Smlf  */
748507c3241Smlf 
749507c3241Smlf void
ata_disk_uninit_drive(ata_drv_t * ata_drvp)750507c3241Smlf ata_disk_uninit_drive(
751507c3241Smlf 	ata_drv_t *ata_drvp)
752507c3241Smlf {
753602ca9eaScth 	struct scsi_device *devp = ata_drvp->ad_device;
754507c3241Smlf 
755507c3241Smlf 	ADBG_TRACE(("ata_disk_uninit_drive entered\n"));
756507c3241Smlf 
757602ca9eaScth 	if (devp) {
758602ca9eaScth 		if (ata_drvp->ad_flags & AD_MUTEX_INIT)
759602ca9eaScth 			mutex_destroy(&devp->sd_mutex);
760602ca9eaScth 		ata_drvp->ad_device = NULL;
761602ca9eaScth 		kmem_free(devp, scsi_device_size());
762602ca9eaScth 	}
763507c3241Smlf }
764507c3241Smlf 
765507c3241Smlf 
766507c3241Smlf 
767507c3241Smlf 
768507c3241Smlf /*
769507c3241Smlf  *
770507c3241Smlf  * DADA compliant bus_ctl entry point
771507c3241Smlf  *
772507c3241Smlf  */
773507c3241Smlf 
774507c3241Smlf /*ARGSUSED*/
775507c3241Smlf int
ata_disk_bus_ctl(dev_info_t * d,dev_info_t * r,ddi_ctl_enum_t o,void * a,void * v)776*1bff1300SToomas Soome ata_disk_bus_ctl(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t o,
777*1bff1300SToomas Soome     void *a, void *v)
778507c3241Smlf {
779507c3241Smlf 	ADBG_TRACE(("ata_disk_bus_ctl entered\n"));
780507c3241Smlf 
781507c3241Smlf 	switch (o) {
782507c3241Smlf 
783507c3241Smlf 	case DDI_CTLOPS_REPORTDEV:
784507c3241Smlf 	{
785507c3241Smlf 		int	targ;
786507c3241Smlf 
787507c3241Smlf 		targ = ddi_prop_get_int(DDI_DEV_T_ANY, r, DDI_PROP_DONTPASS,
788*1bff1300SToomas Soome 		    "target", 0);
789507c3241Smlf 		cmn_err(CE_CONT, "?%s%d at %s%d target %d lun %d\n",
790*1bff1300SToomas Soome 		    ddi_driver_name(r), ddi_get_instance(r),
791*1bff1300SToomas Soome 		    ddi_driver_name(d), ddi_get_instance(d), targ, 0);
792507c3241Smlf 		return (DDI_SUCCESS);
793507c3241Smlf 	}
794507c3241Smlf 	case DDI_CTLOPS_INITCHILD:
795507c3241Smlf 	{
796507c3241Smlf 		dev_info_t	*cdip = (dev_info_t *)a;
797507c3241Smlf 		ata_drv_t	*ata_drvp;
798507c3241Smlf 		ata_ctl_t	*ata_ctlp;
799507c3241Smlf 		ata_tgt_t	*ata_tgtp;
800507c3241Smlf 		struct scsi_device *devp;
801507c3241Smlf 		struct ctl_obj	*ctlobjp;
802507c3241Smlf 		gtgt_t		*gtgtp;
803507c3241Smlf 		char		 name[MAXNAMELEN];
804507c3241Smlf 
805507c3241Smlf 		/*
806507c3241Smlf 		 * save time by picking up ptr to drive struct left
807507c3241Smlf 		 * by ata_bus_ctl - isn't that convenient.
808507c3241Smlf 		 */
809507c3241Smlf 		ata_drvp = ddi_get_driver_private(cdip);
810507c3241Smlf 		ata_ctlp = ata_drvp->ad_ctlp;
811507c3241Smlf 
812507c3241Smlf 		/* set up pointers to child dip */
813507c3241Smlf 
814602ca9eaScth 		devp = ata_drvp->ad_device;
815507c3241Smlf 		/*
816507c3241Smlf 		 * If sd_dev is set, it means that the target has already
817507c3241Smlf 		 * being initialized. The cdip is a duplicate node from
818507c3241Smlf 		 * reexpansion of driver.conf. Fail INITCHILD here.
819507c3241Smlf 		 */
820602ca9eaScth 		if ((devp == NULL) || (devp->sd_dev != NULL)) {
821507c3241Smlf 			return (DDI_FAILURE);
822507c3241Smlf 		}
823507c3241Smlf 		devp->sd_dev = cdip;
824507c3241Smlf 
825507c3241Smlf 		ctlobjp = &ata_drvp->ad_ctl_obj;
826507c3241Smlf 		ctlobjp->c_extblk.c_devdip = cdip;
827507c3241Smlf 
828507c3241Smlf 		/*
829507c3241Smlf 		 * Create the "ata" property for use by the target driver
830507c3241Smlf 		 */
831507c3241Smlf 		if (!ata_prop_create(cdip, ata_drvp, "ata")) {
832507c3241Smlf 			return (DDI_FAILURE);
833507c3241Smlf 		}
834507c3241Smlf 
835507c3241Smlf 		gtgtp = ghd_target_init(d, cdip, &ata_ctlp->ac_ccc,
836*1bff1300SToomas Soome 		    sizeof (ata_tgt_t), ata_ctlp,
837*1bff1300SToomas Soome 		    ata_drvp->ad_targ, ata_drvp->ad_lun);
838507c3241Smlf 
839507c3241Smlf 		/* gt_tgt_private points to ata_tgt_t */
840507c3241Smlf 		ata_tgtp = GTGTP2ATATGTP(gtgtp);
841507c3241Smlf 		ata_tgtp->at_drvp = ata_drvp;
842507c3241Smlf 		ata_tgtp->at_dma_attr = ata_pciide_dma_attr;
843507c3241Smlf 		ata_tgtp->at_dma_attr.dma_attr_maxxfer =
844*1bff1300SToomas Soome 		    ata_ctlp->ac_max_transfer << SCTRSHFT;
845507c3241Smlf 
846507c3241Smlf 		/* gtgtp is the opaque arg to all my entry points */
847507c3241Smlf 		ctlobjp->c_data = gtgtp;
848507c3241Smlf 
849507c3241Smlf 		/* create device name */
850507c3241Smlf 
851507c3241Smlf 		(void) sprintf(name, "%x,%x", ata_drvp->ad_targ,
852*1bff1300SToomas Soome 		    ata_drvp->ad_lun);
853507c3241Smlf 		ddi_set_name_addr(cdip, name);
854507c3241Smlf 		ddi_set_driver_private(cdip, devp);
855507c3241Smlf 
856507c3241Smlf 		return (DDI_SUCCESS);
857507c3241Smlf 	}
858507c3241Smlf 
859507c3241Smlf 	case DDI_CTLOPS_UNINITCHILD:
860507c3241Smlf 	{
861507c3241Smlf 		dev_info_t *cdip = (dev_info_t *)a;
862*1bff1300SToomas Soome 		struct	scsi_device *devp;
863507c3241Smlf 		struct	ctl_obj *ctlobjp;
864507c3241Smlf 		gtgt_t	*gtgtp;
865507c3241Smlf 
866507c3241Smlf 		devp = ddi_get_driver_private(cdip);
867507c3241Smlf 		ctlobjp = (struct ctl_obj *)devp->sd_address.a_hba_tran;
868507c3241Smlf 		gtgtp = ctlobjp->c_data;
869507c3241Smlf 
870507c3241Smlf 		ghd_target_free(d, cdip, &GTGTP2ATAP(gtgtp)->ac_ccc, gtgtp);
871507c3241Smlf 
872507c3241Smlf 		ddi_set_driver_private(cdip, NULL);
873507c3241Smlf 		ddi_set_name_addr(cdip, NULL);
874507c3241Smlf 		return (DDI_SUCCESS);
875507c3241Smlf 	}
876507c3241Smlf 
877507c3241Smlf 	default:
878507c3241Smlf 		return (DDI_FAILURE);
879507c3241Smlf 	}
880507c3241Smlf }
881507c3241Smlf 
882507c3241Smlf 
883507c3241Smlf /*
884507c3241Smlf  *
885507c3241Smlf  * DADA abort entry point - not currently used by dadk
886507c3241Smlf  *
887507c3241Smlf  */
888507c3241Smlf 
889507c3241Smlf /* ARGSUSED */
890507c3241Smlf static int
ata_disk_abort(opaque_t ctl_data,cmpkt_t * pktp)891507c3241Smlf ata_disk_abort(opaque_t ctl_data, cmpkt_t *pktp)
892507c3241Smlf {
893507c3241Smlf 	ADBG_TRACE(("ata_disk_abort entered\n"));
894507c3241Smlf 
895507c3241Smlf 	/* XXX - Note that this interface is currently not used by dadk */
896507c3241Smlf 
897507c3241Smlf 	/*
898507c3241Smlf 	 *  GHD abort functions take a pointer to a scsi_address
899507c3241Smlf 	 *  and so they're unusable here.  The ata driver used to
900507c3241Smlf 	 *  return DDI_SUCCESS here without doing anything.  Its
901507c3241Smlf 	 *  seems that DDI_FAILURE is more appropriate.
902507c3241Smlf 	 */
903507c3241Smlf 
904507c3241Smlf 	return (DDI_FAILURE);
905507c3241Smlf }
906507c3241Smlf 
907507c3241Smlf 
908507c3241Smlf 
909507c3241Smlf /*
910507c3241Smlf  *
911507c3241Smlf  * DADA reset entry point - not currently used by dadk
912507c3241Smlf  * (except in debug versions of driver)
913507c3241Smlf  *
914507c3241Smlf  */
915507c3241Smlf 
916507c3241Smlf /* ARGSUSED */
917507c3241Smlf static int
ata_disk_reset(opaque_t ctl_data,int level)918507c3241Smlf ata_disk_reset(opaque_t ctl_data, int level)
919507c3241Smlf {
920507c3241Smlf 	gtgt_t		*gtgtp = (gtgt_t *)ctl_data;
921507c3241Smlf 	ata_drv_t	*ata_drvp = GTGTP2ATADRVP(gtgtp);
922507c3241Smlf 	int		rc;
923507c3241Smlf 
924507c3241Smlf 	ADBG_TRACE(("ata_disk_reset entered\n"));
925507c3241Smlf 
926507c3241Smlf 	/* XXX - Note that this interface is currently not used by dadk */
927507c3241Smlf 
928*1bff1300SToomas Soome 	switch (level) {
929*1bff1300SToomas Soome 	case RESET_TARGET:
930507c3241Smlf 		rc = ghd_tran_reset_target(&ata_drvp->ad_ctlp->ac_ccc, gtgtp,
931*1bff1300SToomas Soome 		    NULL);
932*1bff1300SToomas Soome 		break;
933*1bff1300SToomas Soome 	case RESET_ALL:
934507c3241Smlf 		rc = ghd_tran_reset_bus(&ata_drvp->ad_ctlp->ac_ccc, gtgtp,
935*1bff1300SToomas Soome 		    NULL);
936*1bff1300SToomas Soome 		break;
937*1bff1300SToomas Soome 	default:
938*1bff1300SToomas Soome 		rc = 0;
939507c3241Smlf 	}
940507c3241Smlf 
941507c3241Smlf 	return (rc ? DDI_SUCCESS : DDI_FAILURE);
942507c3241Smlf }
943507c3241Smlf 
944507c3241Smlf 
945507c3241Smlf 
946507c3241Smlf /*
947507c3241Smlf  *
948507c3241Smlf  * DADA ioctl entry point
949507c3241Smlf  *
950507c3241Smlf  */
951507c3241Smlf 
952507c3241Smlf /* ARGSUSED */
953507c3241Smlf static int
ata_disk_ioctl(opaque_t ctl_data,int cmd,intptr_t arg,int flag)954507c3241Smlf ata_disk_ioctl(opaque_t ctl_data, int cmd, intptr_t arg, int flag)
955507c3241Smlf {
956507c3241Smlf 	gtgt_t		*gtgtp = (gtgt_t *)ctl_data;
957507c3241Smlf 	ata_ctl_t	*ata_ctlp = GTGTP2ATAP(gtgtp);
958507c3241Smlf 	ata_drv_t	*ata_drvp = GTGTP2ATADRVP(gtgtp);
9590f2c99a4Syt 	int		rc, rc2;
9604d27faddSmarx 	struct tgdk_geom tgdk;
9614d27faddSmarx 	int		wce;
962507c3241Smlf 	struct ata_id	*aidp = &ata_drvp->ad_id;
9630f2c99a4Syt 	dk_updatefw_t	updatefw;
9640f2c99a4Syt #ifdef _MULTI_DATAMODEL
9650f2c99a4Syt 	dk_updatefw_32_t updatefw32;
9660f2c99a4Syt #endif
9670f2c99a4Syt 	dk_disk_id_t	dk_disk_id;
9680f2c99a4Syt 	char		buf[80];
9690f2c99a4Syt 	int		i;
9700f2c99a4Syt 
971507c3241Smlf 
972507c3241Smlf 	ADBG_TRACE(("ata_disk_ioctl entered, cmd = %d\n", cmd));
973507c3241Smlf 
974507c3241Smlf 	switch (cmd) {
975507c3241Smlf 
976507c3241Smlf 	case DIOCTL_GETGEOM:
977507c3241Smlf 	case DIOCTL_GETPHYGEOM:
9784d27faddSmarx 		tgdk.g_cyl = ata_drvp->ad_drvrcyl;
9794d27faddSmarx 		tgdk.g_head = ata_drvp->ad_drvrhd;
9804d27faddSmarx 		tgdk.g_sec = ata_drvp->ad_drvrsec;
9814d27faddSmarx 		tgdk.g_acyl = ata_drvp->ad_acyl;
9824d27faddSmarx 		tgdk.g_secsiz = 512;
983cfcc56e0SMark Logan 		tgdk.g_cap = (diskaddr_t)tgdk.g_cyl * tgdk.g_head * tgdk.g_sec;
9844d27faddSmarx 		if (ddi_copyout(&tgdk, (caddr_t)arg, sizeof (tgdk), flag))
9854d27faddSmarx 			return (EFAULT);
986507c3241Smlf 		return (0);
987507c3241Smlf 
988507c3241Smlf 	case DCMD_UPDATE_GEOM:
989*1bff1300SToomas Soome 	/*
990*1bff1300SToomas Soome 	 * ??? fix this to issue IDENTIFY DEVICE ???
991*1bff1300SToomas Soome 	 * might not be necessary since I don't know of any ATA/IDE that
992*1bff1300SToomas Soome 	 * can change its geometry. On the other hand, ATAPI devices like the
993*1bff1300SToomas Soome 	 * LS-120 or PD/CD can change their geometry when new media is inserted
994*1bff1300SToomas Soome 	 */
995507c3241Smlf 		return (0);
996507c3241Smlf 
997507c3241Smlf 	/* copy the model number into the caller's buffer */
998507c3241Smlf 	case DIOCTL_GETMODEL:
999507c3241Smlf 		rc = ata_copy_dk_ioc_string(arg, aidp->ai_model,
1000*1bff1300SToomas Soome 		    sizeof (aidp->ai_model), flag);
1001507c3241Smlf 		return (rc);
1002507c3241Smlf 
10030f2c99a4Syt 	/* copy the serial number into the caller's buffer */
1004507c3241Smlf 	case DIOCTL_GETSERIAL:
1005507c3241Smlf 		rc = ata_copy_dk_ioc_string(arg, aidp->ai_drvser,
1006*1bff1300SToomas Soome 		    sizeof (aidp->ai_drvser), flag);
1007507c3241Smlf 		return (rc);
1008507c3241Smlf 
1009507c3241Smlf 	case DIOCTL_GETWCE:
1010507c3241Smlf 		/*
1011507c3241Smlf 		 * WCE is only supported in ATAPI-4 or higher, for
1012507c3241Smlf 		 * lower rev devices, must assume write cache is
1013507c3241Smlf 		 * enabled.
1014507c3241Smlf 		 * NOTE: Since there is currently no Solaris mechanism
1015507c3241Smlf 		 * to change the state of the Write Cache Enable feature,
1016507c3241Smlf 		 * this code just checks the value of the WCE bit
1017507c3241Smlf 		 * obtained at device init time.  If a mechanism
1018507c3241Smlf 		 * is added to the driver to change WCE, this code
1019507c3241Smlf 		 * must be updated appropriately.
1020507c3241Smlf 		 */
10214d27faddSmarx 		wce = (aidp->ai_majorversion == 0xffff) ||
1022*1bff1300SToomas Soome 		    ((aidp->ai_majorversion & ATAC_MAJVER_4) == 0) ||
1023*1bff1300SToomas Soome 		    (aidp->ai_features85 & ATAC_FEATURES85_WCE) != 0;
10244d27faddSmarx 
10254d27faddSmarx 		if (ddi_copyout(&wce, (caddr_t)arg, sizeof (wce), flag) != 0)
10264d27faddSmarx 			return (EFAULT);
10274d27faddSmarx 
1028507c3241Smlf 		return (0);
1029507c3241Smlf 
1030507c3241Smlf 	case DCMD_GET_STATE:
1031507c3241Smlf 		rc = ata_queue_cmd(ata_disk_state, NULL, ata_ctlp, ata_drvp,
1032*1bff1300SToomas Soome 		    gtgtp);
1033507c3241Smlf 		break;
1034507c3241Smlf 
1035507c3241Smlf 	case DCMD_LOCK:
1036507c3241Smlf 	case DKIOCLOCK:
1037507c3241Smlf 		rc = ata_queue_cmd(ata_disk_lock, NULL, ata_ctlp, ata_drvp,
1038*1bff1300SToomas Soome 		    gtgtp);
1039507c3241Smlf 		break;
1040507c3241Smlf 
1041507c3241Smlf 	case DCMD_UNLOCK:
1042507c3241Smlf 	case DKIOCUNLOCK:
1043507c3241Smlf 		rc = ata_queue_cmd(ata_disk_unlock, NULL, ata_ctlp, ata_drvp,
1044*1bff1300SToomas Soome 		    gtgtp);
1045507c3241Smlf 		break;
1046507c3241Smlf 
1047507c3241Smlf 	case DCMD_START_MOTOR:
1048507c3241Smlf 	case CDROMSTART:
1049507c3241Smlf 		rc = ata_queue_cmd(ata_disk_recalibrate, NULL, ata_ctlp,
1050*1bff1300SToomas Soome 		    ata_drvp, gtgtp);
1051507c3241Smlf 		break;
1052507c3241Smlf 
1053507c3241Smlf 	case DCMD_STOP_MOTOR:
1054507c3241Smlf 	case CDROMSTOP:
1055507c3241Smlf 		rc = ata_queue_cmd(ata_disk_standby, NULL, ata_ctlp, ata_drvp,
1056*1bff1300SToomas Soome 		    gtgtp);
1057507c3241Smlf 		break;
1058507c3241Smlf 
1059507c3241Smlf 	case DKIOCEJECT:
1060507c3241Smlf 	case CDROMEJECT:
1061507c3241Smlf 		rc = ata_queue_cmd(ata_disk_eject, NULL, ata_ctlp, ata_drvp,
1062*1bff1300SToomas Soome 		    gtgtp);
1063507c3241Smlf 		break;
1064507c3241Smlf 
10650f2c99a4Syt 	case DKIOC_UPDATEFW:
10660f2c99a4Syt 
10670f2c99a4Syt 		/*
10680f2c99a4Syt 		 * Call DOWNLOAD MICROCODE command to update device
10690f2c99a4Syt 		 * firmware.
10700f2c99a4Syt 		 *
10710f2c99a4Syt 		 * return value:
10720f2c99a4Syt 		 *   normal	0	Download microcode success
10730f2c99a4Syt 		 *   error	EFAULT	Bad address
10740f2c99a4Syt 		 *		ENXIO	No such device or address
10750f2c99a4Syt 		 *		EINVAL	Invalid argument
10760f2c99a4Syt 		 *		ENOMEM	Not enough core
10770f2c99a4Syt 		 *		ENOTSUP	Operation not supported
10780f2c99a4Syt 		 *		EIO	I/O error
10790f2c99a4Syt 		 *		EPERM	Not owner
10800f2c99a4Syt 		 */
10810f2c99a4Syt 
10820f2c99a4Syt 		/*
10830f2c99a4Syt 		 * The following code deals with handling 32-bit request
10840f2c99a4Syt 		 * in 64-bit kernel.
10850f2c99a4Syt 		 */
10860f2c99a4Syt #ifdef _MULTI_DATAMODEL
10870f2c99a4Syt 		if (ddi_model_convert_from(flag & FMODELS) ==
10880f2c99a4Syt 		    DDI_MODEL_ILP32) {
10890f2c99a4Syt 			if (ddi_copyin((void *)arg, &updatefw32,
10900f2c99a4Syt 			    sizeof (dk_updatefw_32_t), flag))
10910f2c99a4Syt 				return (EFAULT);
10920f2c99a4Syt 
10930f2c99a4Syt 			updatefw.dku_ptrbuf =
10940f2c99a4Syt 			    (caddr_t)(uintptr_t)updatefw32.dku_ptrbuf;
10950f2c99a4Syt 			updatefw.dku_size = updatefw32.dku_size;
10960f2c99a4Syt 			updatefw.dku_type = updatefw32.dku_type;
10970f2c99a4Syt 		} else {
10980f2c99a4Syt 			if (ddi_copyin((void *)arg, &updatefw,
10990f2c99a4Syt 			    sizeof (dk_updatefw_t), flag))
11000f2c99a4Syt 				return (EFAULT);
11010f2c99a4Syt 		}
11020f2c99a4Syt #else
11030f2c99a4Syt 		if (ddi_copyin((void *)arg, &updatefw,
11040f2c99a4Syt 		    sizeof (dk_updatefw_t), flag))
11050f2c99a4Syt 			return (EFAULT);
11060f2c99a4Syt #endif
11070f2c99a4Syt 		rc = ata_disk_update_fw(gtgtp, ata_ctlp, ata_drvp,
11080f2c99a4Syt 		    updatefw.dku_ptrbuf, updatefw.dku_size,
11090f2c99a4Syt 		    updatefw.dku_type, flag);
11100f2c99a4Syt 
11110f2c99a4Syt 		/*
11120f2c99a4Syt 		 * According to ATA8-ACS spec, the new microcode should
11130f2c99a4Syt 		 * become effective immediately after the transfer of the
11140f2c99a4Syt 		 * last data segment has completed, so here we will call
11150f2c99a4Syt 		 * IDENTIFY DEVICE command immediately to update
11160f2c99a4Syt 		 * ata_id content when success.
11170f2c99a4Syt 		 */
11180f2c99a4Syt 		if (rc == 0) {
11190f2c99a4Syt 			rc2 = ata_queue_cmd(ata_disk_id_update, NULL,
11200f2c99a4Syt 			    ata_ctlp, ata_drvp, gtgtp);
11210f2c99a4Syt 			if (rc2 != TRUE) {
11220f2c99a4Syt 				return (ENXIO);
11230f2c99a4Syt 			} else {
11240f2c99a4Syt 				/*
11250f2c99a4Syt 				 * Check whether the content of the IDENTIFY
11260f2c99a4Syt 				 * DEVICE data is incomplete, if yes, it's
11270f2c99a4Syt 				 * because the device supports the Power-up
11280f2c99a4Syt 				 * in Standby feature set, and we will first
11290f2c99a4Syt 				 * check word 2, and then decide whether need
11300f2c99a4Syt 				 * to call set feature to spin-up the device,
11310f2c99a4Syt 				 * and then call IDENTIFY DEVICE command again.
11320f2c99a4Syt 				 */
11330f2c99a4Syt 				aidp = &ata_drvp->ad_id;
11340f2c99a4Syt 				if (aidp->ai_config & ATA_ID_INCMPT) {
11350f2c99a4Syt 					if (aidp->ai_resv0 == 0x37c8 ||
11360f2c99a4Syt 					    aidp->ai_resv0 == 0x738c) {
11370f2c99a4Syt 						/* Spin-up the device */
11380f2c99a4Syt 						(void) ata_queue_cmd(
11390f2c99a4Syt 						    ata_disk_set_feature_spinup,
11400f2c99a4Syt 						    NULL,
11410f2c99a4Syt 						    ata_ctlp,
11420f2c99a4Syt 						    ata_drvp,
11430f2c99a4Syt 						    gtgtp);
11440f2c99a4Syt 					}
11450f2c99a4Syt 
11460f2c99a4Syt 					/* Try to update ata_id again */
11470f2c99a4Syt 					rc2 = ata_queue_cmd(
11480f2c99a4Syt 					    ata_disk_id_update,
11490f2c99a4Syt 					    NULL,
11500f2c99a4Syt 					    ata_ctlp,
11510f2c99a4Syt 					    ata_drvp,
11520f2c99a4Syt 					    gtgtp);
11530f2c99a4Syt 					if (rc2 != TRUE) {
11540f2c99a4Syt 						return (ENXIO);
11550f2c99a4Syt 					} else {
11560f2c99a4Syt 						aidp = &ata_drvp->ad_id;
11570f2c99a4Syt 						if (aidp->ai_config &
11580f2c99a4Syt 						    ATA_ID_INCMPT)
11590f2c99a4Syt 							return (ENXIO);
11600f2c99a4Syt 					}
11610f2c99a4Syt 				}
11620f2c99a4Syt 
11630f2c99a4Syt 				/*
11640f2c99a4Syt 				 * Dump the drive information.
11650f2c99a4Syt 				 */
11660f2c99a4Syt 				ATAPRT(("?\tUpdate firmware of %s device at "
11670f2c99a4Syt 				    "targ %d, lun %d lastlun 0x%x\n",
11680f2c99a4Syt 				    (ATAPIDRV(ata_drvp) ? "ATAPI":"IDE"),
11690f2c99a4Syt 				    ata_drvp->ad_targ, ata_drvp->ad_lun,
11700f2c99a4Syt 				    aidp->ai_lastlun));
11710f2c99a4Syt 
11720f2c99a4Syt 				(void) strncpy(buf, aidp->ai_model,
11730f2c99a4Syt 				    sizeof (aidp->ai_model));
11740f2c99a4Syt 				buf[sizeof (aidp->ai_model)] = '\0';
11750f2c99a4Syt 				for (i = sizeof (aidp->ai_model) - 1;
11760f2c99a4Syt 				    buf[i] == ' '; i--)
11770f2c99a4Syt 					buf[i] = '\0';
11780f2c99a4Syt 				ATAPRT(("?\tmodel %s\n", buf));
11790f2c99a4Syt 
11800f2c99a4Syt 				(void) strncpy(buf, aidp->ai_fw,
11810f2c99a4Syt 				    sizeof (aidp->ai_fw));
11820f2c99a4Syt 				buf[sizeof (aidp->ai_fw)] = '\0';
11830f2c99a4Syt 				for (i = sizeof (aidp->ai_fw) - 1;
11840f2c99a4Syt 				    buf[i] == ' '; i--)
11850f2c99a4Syt 					buf[i] = '\0';
11860f2c99a4Syt 				ATAPRT(("?\tfw %s\n", buf));
11870f2c99a4Syt 			}
11880f2c99a4Syt 		}
11890f2c99a4Syt 		return (rc);
11900f2c99a4Syt 
11910f2c99a4Syt 	case DKIOC_GETDISKID:
11920f2c99a4Syt 		bzero(&dk_disk_id, sizeof (dk_disk_id_t));
11930f2c99a4Syt 
11940f2c99a4Syt 		dk_disk_id.dkd_dtype = DKD_ATA_TYPE;
11950f2c99a4Syt 
11960f2c99a4Syt 		/* Get the model number */
11970f2c99a4Syt 		(void) strncpy(dk_disk_id.disk_id.ata_disk_id.dkd_amodel,
11980f2c99a4Syt 		    aidp->ai_model, sizeof (aidp->ai_model));
11990f2c99a4Syt 
12000f2c99a4Syt 		/* Get the firmware revision */
12010f2c99a4Syt 		(void) strncpy(dk_disk_id.disk_id.ata_disk_id.dkd_afwver,
12020f2c99a4Syt 		    aidp->ai_fw, sizeof (aidp->ai_fw));
12030f2c99a4Syt 
12040f2c99a4Syt 		/* Get the serial number */
12050f2c99a4Syt 		(void) strncpy(dk_disk_id.disk_id.ata_disk_id.dkd_aserial,
12060f2c99a4Syt 		    aidp->ai_drvser, sizeof (aidp->ai_drvser));
12070f2c99a4Syt 
12080f2c99a4Syt 		if (ddi_copyout(&dk_disk_id, (void *)arg,
12090f2c99a4Syt 		    sizeof (dk_disk_id_t), flag))
12100f2c99a4Syt 			return (EFAULT);
12110f2c99a4Syt 		else
12120f2c99a4Syt 			return (0);
12130f2c99a4Syt 
1214507c3241Smlf 	default:
1215507c3241Smlf 		ADBG_WARN(("ata_disk_ioctl: unsupported cmd 0x%x\n", cmd));
1216507c3241Smlf 		return (ENOTTY);
1217507c3241Smlf 	}
1218507c3241Smlf 
1219507c3241Smlf 	if (rc)
1220507c3241Smlf 		return (0);
1221507c3241Smlf 	return (ENXIO);
1222507c3241Smlf 
1223507c3241Smlf }
1224507c3241Smlf 
1225507c3241Smlf 
1226507c3241Smlf #ifdef ___not___used___
1227507c3241Smlf /*
1228507c3241Smlf  * Issue an ATA command to the drive using the packet already
1229507c3241Smlf  * allocated by the target driver
1230507c3241Smlf  */
1231507c3241Smlf 
1232507c3241Smlf int
ata_disk_do_ioctl(int (* func)(ata_ctl_t *,ata_drv_t *,ata_pkt_t *),void * arg,ata_ctl_t * ata_ctlp,gtgt_t * gtgtp,cmpkt_t * pktp)1233*1bff1300SToomas Soome ata_disk_do_ioctl(int (*func)(ata_ctl_t *, ata_drv_t *, ata_pkt_t *),
1234*1bff1300SToomas Soome     void *arg, ata_ctl_t *ata_ctlp, gtgt_t *gtgtp, cmpkt_t *pktp)
1235507c3241Smlf {
1236507c3241Smlf 	gcmd_t	  *gcmdp = CPKT2GCMD(pktp);
1237507c3241Smlf 	ata_pkt_t *ata_pktp = GCMD2APKT(gcmdp);
1238507c3241Smlf 	int	   rc;
1239507c3241Smlf 
1240507c3241Smlf 	ata_pktp->ap_start = func;
1241507c3241Smlf 	ata_pktp->ap_intr = NULL;
1242507c3241Smlf 	ata_pktp->ap_complete = NULL;
1243507c3241Smlf 	ata_pktp->ap_v_addr = (caddr_t)arg;
1244507c3241Smlf 
1245507c3241Smlf 	/*
1246507c3241Smlf 	 * add it to the queue, when it gets to the front the
1247507c3241Smlf 	 * ap_start function is called.
1248507c3241Smlf 	 */
1249507c3241Smlf 	rc = ghd_transport(&ata_ctlp->ac_ccc, gcmdp, gcmdp->cmd_gtgtp,
1250*1bff1300SToomas Soome 	    0, TRUE, NULL);
1251507c3241Smlf 
1252507c3241Smlf 	if (rc != TRAN_ACCEPT) {
1253507c3241Smlf 		/* this should never, ever happen */
1254507c3241Smlf 		return (ENXIO);
1255507c3241Smlf 	}
1256507c3241Smlf 
1257507c3241Smlf 	if (ata_pktp->ap_flags & AP_ERROR)
1258507c3241Smlf 		return (ENXIO);
1259507c3241Smlf 	return (0);
1260507c3241Smlf }
1261507c3241Smlf #endif
1262507c3241Smlf 
1263507c3241Smlf 
1264507c3241Smlf 
1265507c3241Smlf /*
1266507c3241Smlf  *
1267507c3241Smlf  * DADA pktalloc entry point
1268507c3241Smlf  *
1269507c3241Smlf  */
1270507c3241Smlf 
1271507c3241Smlf /* ARGSUSED */
1272507c3241Smlf static cmpkt_t *
ata_disk_pktalloc(opaque_t ctl_data,int (* callback)(caddr_t),caddr_t arg)1273507c3241Smlf ata_disk_pktalloc(opaque_t ctl_data, int (*callback)(caddr_t), caddr_t arg)
1274507c3241Smlf {
1275507c3241Smlf 	gtgt_t		*gtgtp = (gtgt_t *)ctl_data;
1276507c3241Smlf 	ata_drv_t	*ata_drvp = GTGTP2ATADRVP(gtgtp);
1277507c3241Smlf 	cmpkt_t		*pktp;
1278507c3241Smlf 	ata_pkt_t	*ata_pktp;
1279507c3241Smlf 	gcmd_t		*gcmdp;
1280507c3241Smlf 
1281507c3241Smlf 	ADBG_TRACE(("ata_disk_pktalloc entered\n"));
1282507c3241Smlf 
1283507c3241Smlf 	/*
1284507c3241Smlf 	 * Allocate and  init the GHD gcmd_t structure and the
1285507c3241Smlf 	 * DADA cmpkt and the ata_pkt
1286507c3241Smlf 	 */
1287507c3241Smlf 	if ((gcmdp = ghd_gcmd_alloc(gtgtp,
1288*1bff1300SToomas Soome 	    (sizeof (cmpkt_t) + sizeof (ata_pkt_t)),
1289*1bff1300SToomas Soome 	    (callback == DDI_DMA_SLEEP))) == NULL) {
1290507c3241Smlf 		return ((cmpkt_t *)NULL);
1291507c3241Smlf 	}
1292507c3241Smlf 	ASSERT(gcmdp != NULL);
1293507c3241Smlf 
1294507c3241Smlf 	ata_pktp = GCMD2APKT(gcmdp);
1295507c3241Smlf 	ASSERT(ata_pktp != NULL);
1296507c3241Smlf 
1297507c3241Smlf 	pktp = (cmpkt_t *)(ata_pktp + 1);
1298507c3241Smlf 
1299507c3241Smlf 	pktp->cp_ctl_private = (void *)gcmdp;
1300507c3241Smlf 	ata_pktp->ap_gcmdp = gcmdp;
1301507c3241Smlf 	gcmdp->cmd_pktp = (void *)pktp;
1302507c3241Smlf 
1303507c3241Smlf 	/*
1304507c3241Smlf 	 * At this point the structures are linked like this:
1305507c3241Smlf 	 *
1306507c3241Smlf 	 *	(struct cmpkt) <--> (struct gcmd) <--> (struct ata_pkt)
1307507c3241Smlf 	 */
1308507c3241Smlf 
1309507c3241Smlf 	/* callback functions */
1310507c3241Smlf 
1311507c3241Smlf 	ata_pktp->ap_start = ata_disk_start;
1312507c3241Smlf 	ata_pktp->ap_intr = ata_disk_intr;
1313507c3241Smlf 	ata_pktp->ap_complete = ata_disk_complete;
1314507c3241Smlf 
1315507c3241Smlf 	/* other ata_pkt setup */
1316507c3241Smlf 
1317507c3241Smlf 	ata_pktp->ap_bytes_per_block = ata_drvp->ad_bytes_per_block;
1318507c3241Smlf 
1319507c3241Smlf 	/* cmpkt setup */
1320507c3241Smlf 
1321507c3241Smlf 	pktp->cp_cdblen = 1;
1322507c3241Smlf 	pktp->cp_cdbp   = (opaque_t)&ata_pktp->ap_cdb;
1323507c3241Smlf 	pktp->cp_scbp   = (opaque_t)&ata_pktp->ap_scb;
1324507c3241Smlf 	pktp->cp_scblen = 1;
1325507c3241Smlf 
1326507c3241Smlf 	return (pktp);
1327507c3241Smlf }
1328507c3241Smlf 
1329507c3241Smlf 
1330507c3241Smlf 
1331507c3241Smlf /*
1332507c3241Smlf  *
1333507c3241Smlf  * DADA pktfree entry point
1334507c3241Smlf  *
1335507c3241Smlf  */
1336507c3241Smlf 
1337507c3241Smlf /* ARGSUSED */
1338507c3241Smlf static void
ata_disk_pktfree(opaque_t ctl_data,cmpkt_t * pktp)1339507c3241Smlf ata_disk_pktfree(opaque_t ctl_data, cmpkt_t *pktp)
1340507c3241Smlf {
1341507c3241Smlf 	ata_pkt_t *ata_pktp = CPKT2APKT(pktp);
1342507c3241Smlf 
1343507c3241Smlf 	ADBG_TRACE(("ata_disk_pktfree entered\n"));
1344507c3241Smlf 
1345507c3241Smlf 	/* check not free already */
1346507c3241Smlf 
1347507c3241Smlf 	ASSERT(!(ata_pktp->ap_flags & AP_FREE));
1348507c3241Smlf 	ata_pktp->ap_flags = AP_FREE;
1349507c3241Smlf 
1350507c3241Smlf 	ghd_gcmd_free(CPKT2GCMD(pktp));
1351507c3241Smlf }
1352507c3241Smlf 
1353507c3241Smlf 
1354507c3241Smlf /*
1355507c3241Smlf  *
1356507c3241Smlf  * DADA memsetup entry point
1357507c3241Smlf  *
1358507c3241Smlf  */
1359507c3241Smlf 
1360507c3241Smlf /* ARGSUSED */
1361507c3241Smlf static cmpkt_t *
ata_disk_memsetup(opaque_t ctl_data,cmpkt_t * pktp,struct buf * bp,int (* callback)(caddr_t),caddr_t arg)1362507c3241Smlf ata_disk_memsetup(
1363507c3241Smlf 	opaque_t ctl_data,
1364507c3241Smlf 	cmpkt_t *pktp,
1365507c3241Smlf 	struct buf *bp,
1366507c3241Smlf 	int (*callback)(caddr_t),
1367507c3241Smlf 	caddr_t arg)
1368507c3241Smlf {
1369507c3241Smlf 	gtgt_t		*gtgtp = (gtgt_t *)ctl_data;
1370507c3241Smlf 	ata_pkt_t	*ata_pktp = CPKT2APKT(pktp);
1371507c3241Smlf 	gcmd_t		*gcmdp = APKT2GCMD(ata_pktp);
1372507c3241Smlf 	int		flags;
1373507c3241Smlf 
1374507c3241Smlf 	ADBG_TRACE(("ata_disk_memsetup entered\n"));
1375507c3241Smlf 
1376507c3241Smlf 	ata_pktp->ap_sg_cnt = 0;
1377507c3241Smlf 
1378507c3241Smlf 	if (bp->b_bcount == 0) {
1379507c3241Smlf 		ata_pktp->ap_v_addr = NULL;
1380507c3241Smlf 		return (pktp);
1381507c3241Smlf 	}
1382507c3241Smlf 
1383507c3241Smlf 	if (GTGTP2ATADRVP(gtgtp)->ad_pciide_dma != ATA_DMA_ON)
1384507c3241Smlf 		goto skip_dma_setup;
1385507c3241Smlf 
1386507c3241Smlf 	if (ata_dma_disabled)
1387507c3241Smlf 		goto skip_dma_setup;
1388507c3241Smlf 
1389507c3241Smlf 	/*
1390507c3241Smlf 	 * The PCI-IDE DMA engine is brain-damaged and can't
1391507c3241Smlf 	 * DMA non-aligned buffers.
1392507c3241Smlf 	 */
1393507c3241Smlf 	if (!(bp->b_flags & B_PAGEIO) &&
1394507c3241Smlf 	    ((uintptr_t)bp->b_un.b_addr) & PCIIDE_PRDE_ADDR_MASK) {
1395507c3241Smlf 		goto skip_dma_setup;
1396507c3241Smlf 	}
1397507c3241Smlf 
1398507c3241Smlf 	/*
1399507c3241Smlf 	 * It also insists that the byte count must be even.
1400507c3241Smlf 	 */
1401507c3241Smlf 	if (bp->b_bcount & 1)
1402507c3241Smlf 		goto skip_dma_setup;
1403507c3241Smlf 
1404507c3241Smlf 	/* check direction for data transfer */
1405507c3241Smlf 	if (bp->b_flags & B_READ) {
1406507c3241Smlf 		flags = DDI_DMA_READ | DDI_DMA_PARTIAL;
1407507c3241Smlf 	} else {
1408507c3241Smlf 		flags = DDI_DMA_WRITE | DDI_DMA_PARTIAL;
1409507c3241Smlf 	}
1410507c3241Smlf 
1411507c3241Smlf 	/*
1412507c3241Smlf 	 * Bind the DMA handle to the buf
1413507c3241Smlf 	 */
1414507c3241Smlf 	if (ghd_dma_buf_bind_attr(&GTGTP2ATAP(gtgtp)->ac_ccc, gcmdp, bp, flags,
1415*1bff1300SToomas Soome 	    callback, arg, &GTGTP2ATATGTP(gtgtp)->at_dma_attr)) {
1416507c3241Smlf 		ata_pktp->ap_v_addr = 0;
1417507c3241Smlf 		return (pktp);
1418507c3241Smlf 	}
1419507c3241Smlf 
1420507c3241Smlf skip_dma_setup:
1421507c3241Smlf 	bp_mapin(bp);
1422507c3241Smlf 	ata_pktp->ap_v_addr = bp->b_un.b_addr;
1423507c3241Smlf 	return (pktp);
1424507c3241Smlf }
1425507c3241Smlf 
1426507c3241Smlf 
1427507c3241Smlf 
1428507c3241Smlf /*
1429507c3241Smlf  *
1430507c3241Smlf  * DADA memfree entry point
1431507c3241Smlf  *
1432507c3241Smlf  */
1433507c3241Smlf 
1434507c3241Smlf /*
1435507c3241Smlf  * 1157317 sez that drivers shouldn't call bp_mapout(), as either
1436507c3241Smlf  * biodone() or biowait() will end up doing it, but after they
1437507c3241Smlf  * call bp->b_iodone(), which is a necessary sequence for
1438507c3241Smlf  * Online Disk Suite.  However, the DDI group wants to rethink
1439507c3241Smlf  * bp_mapin()/bp_mapout() and how they should behave in the
1440507c3241Smlf  * presence of layered drivers, etc.  For the moment, fix
1441507c3241Smlf  * the OLDS problem by removing the bp_mapout() call.
1442507c3241Smlf  */
1443507c3241Smlf 
1444507c3241Smlf #define	BUG_1157317
1445507c3241Smlf 
1446507c3241Smlf /* ARGSUSED */
1447507c3241Smlf static void
ata_disk_memfree(opaque_t ctl_data,cmpkt_t * pktp)1448507c3241Smlf ata_disk_memfree(opaque_t ctl_data, cmpkt_t *pktp)
1449507c3241Smlf {
1450507c3241Smlf 	gcmd_t	*gcmdp = CPKT2GCMD(pktp);
1451507c3241Smlf 
1452507c3241Smlf 	ADBG_TRACE(("ata_disk_memfree entered\n"));
1453507c3241Smlf 
1454507c3241Smlf 	if (gcmdp->cmd_dma_handle)
1455507c3241Smlf 		ghd_dmafree_attr(gcmdp);
1456507c3241Smlf #if !defined(BUG_1157317)
1457507c3241Smlf 	else
1458507c3241Smlf 		bp_mapout(pktp->cp_bp);
1459507c3241Smlf #endif
1460507c3241Smlf }
1461507c3241Smlf 
1462507c3241Smlf 
1463507c3241Smlf 
1464507c3241Smlf /*
1465507c3241Smlf  *
1466507c3241Smlf  * DADA iosetup entry point
1467507c3241Smlf  *
1468507c3241Smlf  */
1469507c3241Smlf 
1470507c3241Smlf static cmpkt_t *
ata_disk_iosetup(opaque_t ctl_data,cmpkt_t * pktp)1471507c3241Smlf ata_disk_iosetup(opaque_t ctl_data, cmpkt_t *pktp)
1472507c3241Smlf {
1473507c3241Smlf 	gtgt_t		*gtgtp = (gtgt_t *)ctl_data;
1474507c3241Smlf 	ata_drv_t	*ata_drvp = GTGTP2ATADRVP(gtgtp);
1475507c3241Smlf 	ata_pkt_t	*ata_pktp = CPKT2APKT(pktp);
1476507c3241Smlf 	gcmd_t		*gcmdp = APKT2GCMD(ata_pktp);
1477507c3241Smlf 	uint_t		sec_count;
1478507c3241Smlf 	daddr_t		start_sec;
1479507c3241Smlf 	uint_t		byte_count;
1480507c3241Smlf 
1481507c3241Smlf 	ADBG_TRACE(("ata_disk_iosetup entered\n"));
1482507c3241Smlf 
1483507c3241Smlf 	/*
1484507c3241Smlf 	 * Check for DCMD_FLUSH_CACHE (which does no I/O) and
1485507c3241Smlf 	 * just do basic setup.
1486507c3241Smlf 	 */
1487507c3241Smlf 	if (pktp->cp_passthru == NULL &&
1488507c3241Smlf 	    ata_pktp->ap_cdb == DCMD_FLUSH_CACHE) {
1489507c3241Smlf 		ata_pktp->ap_cmd = ATC_FLUSH_CACHE;
1490507c3241Smlf 		ata_pktp->ap_flags = 0;
1491507c3241Smlf 		ata_pktp->ap_count = 0;
1492507c3241Smlf 		ata_pktp->ap_startsec = 0;
1493507c3241Smlf 		ata_pktp->ap_sg_cnt = 0;
1494507c3241Smlf 		ata_pktp->ap_pciide_dma = FALSE;
1495507c3241Smlf 		return (pktp);
1496507c3241Smlf 	}
1497507c3241Smlf 
1498507c3241Smlf 	/* check for error retry */
1499507c3241Smlf 	if (ata_pktp->ap_flags & AP_ERROR) {
1500507c3241Smlf 		/*
1501507c3241Smlf 		 * this is a temporary work-around for dadk calling
1502507c3241Smlf 		 * iosetup for retry. The correct
1503507c3241Smlf 		 * solution is changing dadk to not to call iosetup
1504507c3241Smlf 		 * for a retry.
1505507c3241Smlf 		 * We do not apply the work-around for pio mode since
1506507c3241Smlf 		 * that does not involve moving dma windows and reducing the
1507507c3241Smlf 		 * sector count would work for pio mode on a retry
1508507c3241Smlf 		 * for now.
1509507c3241Smlf 		 */
1510507c3241Smlf 		if (gcmdp->cmd_dma_handle != NULL) {
1511507c3241Smlf 			ata_pktp->ap_flags = 0;
1512507c3241Smlf 			return (NULL);
1513507c3241Smlf 		}
1514507c3241Smlf 
1515507c3241Smlf 		ata_pktp->ap_bytes_per_block = NBPSCTR;
1516507c3241Smlf 		sec_count = 1;
1517507c3241Smlf 
1518507c3241Smlf 		/*
1519507c3241Smlf 		 * Since we are retrying the last read or write operation,
1520507c3241Smlf 		 * restore the old values of the ap_v_addr and ap_resid.
1521507c3241Smlf 		 * This assumes CTL_IOSETUP is called again on retry; if not,
1522507c3241Smlf 		 * this needs to be done in CTL_TRANSPORT.
1523507c3241Smlf 		 */
1524507c3241Smlf 		if (ata_pktp->ap_flags & (AP_READ | AP_WRITE)) {
1525507c3241Smlf 			ata_pktp->ap_v_addr = ata_pktp->ap_v_addr_sav;
1526507c3241Smlf 			ata_pktp->ap_resid = ata_pktp->ap_resid_sav;
1527507c3241Smlf 		}
1528507c3241Smlf 	} else {
1529507c3241Smlf 		/*
1530507c3241Smlf 		 * Limit request to ac_max_transfer sectors.
1531507c3241Smlf 		 * The value is specified by the user in the
1532507c3241Smlf 		 * max_transfer property. It must be in the range 1 to 256.
1533507c3241Smlf 		 * When max_transfer is 0x100 it is bigger than 8 bits.
1534507c3241Smlf 		 * The spec says 0 represents 256 so it should be OK.
1535507c3241Smlf 		 */
1536507c3241Smlf 		sec_count = min((pktp->cp_bytexfer >> SCTRSHFT),
1537*1bff1300SToomas Soome 		    ata_drvp->ad_ctlp->ac_max_transfer);
1538507c3241Smlf 		/*
1539507c3241Smlf 		 * Save the current values of ap_v_addr and ap_resid
1540507c3241Smlf 		 * in case a retry operation happens. During a retry
1541507c3241Smlf 		 * operation we need to restore these values.
1542507c3241Smlf 		 */
1543507c3241Smlf 		ata_pktp->ap_v_addr_sav = ata_pktp->ap_v_addr;
1544507c3241Smlf 		ata_pktp->ap_resid_sav = ata_pktp->ap_resid;
1545507c3241Smlf 	}
1546507c3241Smlf 
1547507c3241Smlf 	/* reset flags */
1548507c3241Smlf 	ata_pktp->ap_flags = 0;
1549507c3241Smlf 
1550507c3241Smlf #ifdef	DADKIO_RWCMD_READ
1551507c3241Smlf 	start_sec = pktp->cp_passthru ? RWCMDP(pktp)->blkaddr : pktp->cp_srtsec;
1552507c3241Smlf #else
1553507c3241Smlf 	start_sec = pktp->cp_srtsec;
1554507c3241Smlf #endif
1555507c3241Smlf 
1556507c3241Smlf 	/*
1557507c3241Smlf 	 * Setup the PCIDE Bus Master Scatter/Gather list
1558507c3241Smlf 	 */
1559507c3241Smlf 	ata_pktp->ap_sg_cnt = 0;
1560507c3241Smlf 	ata_pktp->ap_pciide_dma = FALSE;
1561507c3241Smlf 	if (gcmdp->cmd_dma_handle != NULL && sec_count != 0) {
1562507c3241Smlf 		byte_count = sec_count << SCTRSHFT;
1563507c3241Smlf 		if ((ghd_dmaget_attr(&GTGTP2ATAP(gtgtp)->ac_ccc, gcmdp,
1564*1bff1300SToomas Soome 		    byte_count, ATA_DMA_NSEGS, &byte_count) == FALSE) ||
1565*1bff1300SToomas Soome 		    (byte_count == 0)) {
1566507c3241Smlf 			ADBG_ERROR(("ata_disk_iosetup: byte count zero\n"));
1567507c3241Smlf 			return (NULL);
1568507c3241Smlf 		}
1569507c3241Smlf 		sec_count = byte_count >> SCTRSHFT;
1570507c3241Smlf 	}
1571507c3241Smlf 
1572507c3241Smlf 	/*
1573507c3241Smlf 	 * In the non-48-bit mode addressing (CHS and LBA28) the sector
1574507c3241Smlf 	 * count is a 8-bit value and the sector count 0 represents 256
1575507c3241Smlf 	 * sectors.
1576507c3241Smlf 	 * In the extended addressing (LBA48) the sector count is a 16-bit
1577507c3241Smlf 	 * value, so max_transfer 0x100 cannot be truncated to 8-bits
1578507c3241Smlf 	 * because this would represent a zero sector count.
1579507c3241Smlf 	 */
1580f304523cSzhongyan gu - Sun Microsystems - Beijing China 	ata_pktp->ap_count = (ushort_t)sec_count;
1581507c3241Smlf 	if (!(ata_drvp->ad_flags & AD_EXT48)) {
1582507c3241Smlf 		ata_pktp->ap_count &= 0xff;
1583507c3241Smlf 	}
1584507c3241Smlf 	ata_pktp->ap_startsec = start_sec;
1585507c3241Smlf 
1586507c3241Smlf #ifdef	DADKIO_RWCMD_READ
1587507c3241Smlf 	if (pktp->cp_passthru) {
1588507c3241Smlf 		switch (RWCMDP(pktp)->cmd) {
1589507c3241Smlf 		case DADKIO_RWCMD_READ:
1590507c3241Smlf 			if (ata_pktp->ap_sg_cnt) {
1591507c3241Smlf 				ata_pktp->ap_cmd = ATC_READ_DMA;
1592507c3241Smlf 				ata_pktp->ap_pciide_dma = TRUE;
1593507c3241Smlf 				ata_pktp->ap_start = ata_disk_start_dma_in;
1594507c3241Smlf 				ata_pktp->ap_intr = ata_disk_intr_dma;
1595507c3241Smlf 			} else {
1596507c3241Smlf 				ata_pktp->ap_cmd = ATC_RDSEC;
1597507c3241Smlf 				ata_pktp->ap_start = ata_disk_start_pio_in;
1598507c3241Smlf 				ata_pktp->ap_intr = ata_disk_intr_pio_in;
1599507c3241Smlf 			}
1600507c3241Smlf 			ata_pktp->ap_flags |= AP_READ;
1601507c3241Smlf 			break;
1602507c3241Smlf 		case DADKIO_RWCMD_WRITE:
1603507c3241Smlf 			if (ata_pktp->ap_sg_cnt) {
1604507c3241Smlf 				ata_pktp->ap_cmd = ATC_WRITE_DMA;
1605507c3241Smlf 				ata_pktp->ap_pciide_dma = TRUE;
1606507c3241Smlf 				ata_pktp->ap_start = ata_disk_start_dma_out;
1607507c3241Smlf 				ata_pktp->ap_intr = ata_disk_intr_dma;
1608507c3241Smlf 			} else {
1609507c3241Smlf 				ata_pktp->ap_cmd = ATC_WRSEC;
1610507c3241Smlf 				ata_pktp->ap_start = ata_disk_start_pio_out;
1611507c3241Smlf 				ata_pktp->ap_intr = ata_disk_intr_pio_out;
1612507c3241Smlf 			}
1613507c3241Smlf 			ata_pktp->ap_flags |= AP_WRITE;
1614507c3241Smlf 			break;
1615507c3241Smlf 		}
1616507c3241Smlf 
1617507c3241Smlf 		byte_count = RWCMDP(pktp)->buflen;
1618507c3241Smlf 		pktp->cp_bytexfer = byte_count;
1619507c3241Smlf 		pktp->cp_resid = byte_count;
1620507c3241Smlf 		ata_pktp->ap_resid = byte_count;
1621507c3241Smlf 
1622507c3241Smlf 		/*
1623507c3241Smlf 		 * since we're not using READ/WRITE MULTIPLE, we
1624507c3241Smlf 		 * should set bytes_per_block to one sector
1625507c3241Smlf 		 * XXX- why wasn't this in the old driver??
1626507c3241Smlf 		 */
1627507c3241Smlf 		ata_pktp->ap_bytes_per_block = NBPSCTR;
1628507c3241Smlf 	} else
1629507c3241Smlf #endif
1630507c3241Smlf 	{
1631507c3241Smlf 		byte_count = sec_count << SCTRSHFT;
1632507c3241Smlf 		pktp->cp_bytexfer = byte_count;
1633507c3241Smlf 		pktp->cp_resid = byte_count;
1634507c3241Smlf 		ata_pktp->ap_resid = byte_count;
1635507c3241Smlf 
1636507c3241Smlf 		/* setup the task file registers */
1637507c3241Smlf 
1638507c3241Smlf 		switch (ata_pktp->ap_cdb) {
1639507c3241Smlf 		case DCMD_READ:
1640507c3241Smlf 			if (ata_pktp->ap_sg_cnt) {
1641507c3241Smlf 				ata_pktp->ap_cmd = ATC_READ_DMA;
1642507c3241Smlf 				ata_pktp->ap_pciide_dma = TRUE;
1643507c3241Smlf 				ata_pktp->ap_start = ata_disk_start_dma_in;
1644507c3241Smlf 				ata_pktp->ap_intr = ata_disk_intr_dma;
1645507c3241Smlf 			} else {
1646507c3241Smlf 				ata_pktp->ap_cmd = ata_drvp->ad_rd_cmd;
1647507c3241Smlf 				ata_pktp->ap_start = ata_disk_start_pio_in;
1648507c3241Smlf 				ata_pktp->ap_intr = ata_disk_intr_pio_in;
1649507c3241Smlf 			}
1650507c3241Smlf 			ata_pktp->ap_flags |= AP_READ;
1651507c3241Smlf 			break;
1652507c3241Smlf 
1653507c3241Smlf 		case DCMD_WRITE:
1654507c3241Smlf 			if (ata_pktp->ap_sg_cnt) {
1655507c3241Smlf 				ata_pktp->ap_cmd = ATC_WRITE_DMA;
1656507c3241Smlf 				ata_pktp->ap_pciide_dma = TRUE;
1657507c3241Smlf 				ata_pktp->ap_start = ata_disk_start_dma_out;
1658507c3241Smlf 				ata_pktp->ap_intr = ata_disk_intr_dma;
1659507c3241Smlf 			} else {
1660507c3241Smlf 				ata_pktp->ap_cmd = ata_drvp->ad_wr_cmd;
1661507c3241Smlf 				ata_pktp->ap_start = ata_disk_start_pio_out;
1662507c3241Smlf 				ata_pktp->ap_intr = ata_disk_intr_pio_out;
1663507c3241Smlf 			}
1664507c3241Smlf 			ata_pktp->ap_flags |= AP_WRITE;
1665507c3241Smlf 			break;
1666507c3241Smlf 
1667507c3241Smlf 		default:
1668507c3241Smlf 			ADBG_WARN(("ata_disk_iosetup: unknown command 0x%x\n",
1669*1bff1300SToomas Soome 			    ata_pktp->ap_cdb));
1670507c3241Smlf 			pktp = NULL;
1671507c3241Smlf 			break;
1672507c3241Smlf 		}
1673507c3241Smlf 	}
1674507c3241Smlf 
1675507c3241Smlf 	/* If 48-bit mode is used, convert command to 48-bit mode cmd */
1676507c3241Smlf 	if (pktp != NULL && ata_drvp->ad_flags & AD_EXT48) {
1677507c3241Smlf 		switch (ata_pktp->ap_cmd) {
1678507c3241Smlf 		case ATC_RDSEC:
1679507c3241Smlf 			ata_pktp->ap_cmd = ATC_RDSEC_EXT;
1680507c3241Smlf 			break;
1681507c3241Smlf 		case ATC_WRSEC:
1682507c3241Smlf 			ata_pktp->ap_cmd = ATC_WRSEC_EXT;
1683507c3241Smlf 			break;
1684507c3241Smlf 		case ATC_RDMULT:
1685507c3241Smlf 			ata_pktp->ap_cmd = ATC_RDMULT_EXT;
1686507c3241Smlf 			break;
1687507c3241Smlf 		case ATC_WRMULT:
1688507c3241Smlf 			ata_pktp->ap_cmd = ATC_WRMULT_EXT;
1689507c3241Smlf 			break;
1690507c3241Smlf 		case ATC_READ_DMA:
1691507c3241Smlf 			ata_pktp->ap_cmd = ATC_RDDMA_EXT;
1692507c3241Smlf 			break;
1693507c3241Smlf 		case ATC_WRITE_DMA:
1694507c3241Smlf 			ata_pktp->ap_cmd = ATC_WRDMA_EXT;
1695507c3241Smlf 			break;
1696507c3241Smlf 		}
1697507c3241Smlf 	}
1698507c3241Smlf 
1699507c3241Smlf 	return (pktp);
1700507c3241Smlf }
1701507c3241Smlf 
1702507c3241Smlf 
1703507c3241Smlf 
1704507c3241Smlf /*
1705507c3241Smlf  *
1706507c3241Smlf  * DADA transport entry point
1707507c3241Smlf  *
1708507c3241Smlf  */
1709507c3241Smlf 
1710507c3241Smlf static int
ata_disk_transport(opaque_t ctl_data,cmpkt_t * pktp)1711507c3241Smlf ata_disk_transport(opaque_t ctl_data, cmpkt_t *pktp)
1712507c3241Smlf {
1713507c3241Smlf 	gtgt_t		*gtgtp = (gtgt_t *)ctl_data;
1714507c3241Smlf 	ata_drv_t	*ata_drvp = GTGTP2ATADRVP(gtgtp);
1715507c3241Smlf 	ata_ctl_t	*ata_ctlp = ata_drvp->ad_ctlp;
1716507c3241Smlf 	ata_pkt_t	*ata_pktp = CPKT2APKT(pktp);
1717507c3241Smlf 	int		rc;
1718507c3241Smlf 	int		polled = FALSE;
1719507c3241Smlf 
1720507c3241Smlf 	ADBG_TRACE(("ata_disk_transport entered\n"));
1721507c3241Smlf 
1722507c3241Smlf 	/* check for polling pkt */
1723507c3241Smlf 
1724507c3241Smlf 	if (pktp->cp_flags & CPF_NOINTR) {
1725507c3241Smlf 		polled = TRUE;
1726507c3241Smlf 	}
1727507c3241Smlf 
1728507c3241Smlf 	/* call ghd transport routine */
1729507c3241Smlf 
1730507c3241Smlf 	rc = ghd_transport(&ata_ctlp->ac_ccc, APKT2GCMD(ata_pktp),
1731*1bff1300SToomas Soome 	    gtgtp, pktp->cp_time, polled, NULL);
1732507c3241Smlf 
1733507c3241Smlf 	/* see if pkt was not accepted */
1734507c3241Smlf 
1735507c3241Smlf 	if (rc == TRAN_BUSY)
1736507c3241Smlf 		return (CTL_SEND_BUSY);
1737507c3241Smlf 
1738507c3241Smlf 	if (rc == TRAN_ACCEPT)
1739507c3241Smlf 		return (CTL_SEND_SUCCESS);
1740507c3241Smlf 
1741507c3241Smlf 	return (CTL_SEND_FAILURE);
1742507c3241Smlf }
1743507c3241Smlf 
1744507c3241Smlf 
1745507c3241Smlf /*
1746507c3241Smlf  *
1747507c3241Smlf  * routines to load the cylinder/head/sector/count
1748507c3241Smlf  * task file registers.
1749507c3241Smlf  *
1750507c3241Smlf  */
1751507c3241Smlf static void
ata_disk_load_regs_lba28(ata_pkt_t * ata_pktp,ata_drv_t * ata_drvp)1752507c3241Smlf ata_disk_load_regs_lba28(ata_pkt_t *ata_pktp, ata_drv_t *ata_drvp)
1753507c3241Smlf {
1754507c3241Smlf 	ata_ctl_t	*ata_ctlp = ata_drvp->ad_ctlp;
1755507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
1756507c3241Smlf 	uint_t		lba;	/* LBA of first sector */
1757507c3241Smlf 
1758507c3241Smlf 	lba = ata_pktp->ap_startsec;
1759507c3241Smlf 
1760*1bff1300SToomas Soome 	ddi_put8(io_hdl1, ata_ctlp->ac_count, ata_pktp->ap_count);
1761507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_sect, lba);
1762507c3241Smlf 	lba >>= 8;
1763507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_lcyl, lba);
1764507c3241Smlf 	lba >>= 8;
1765507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_hcyl, lba);
1766507c3241Smlf 	lba >>= 8;
1767507c3241Smlf 	/*
1768507c3241Smlf 	 * dev/head register can use only 4 bits
1769507c3241Smlf 	 * must also include drive selector.
1770507c3241Smlf 	 */
1771507c3241Smlf 	lba = (lba & 0xf) | ata_drvp->ad_drive_bits;
1772507c3241Smlf 	ddi_put8(io_hdl1,  ata_ctlp->ac_drvhd, lba);
1773507c3241Smlf }
1774507c3241Smlf 
1775507c3241Smlf /*
1776507c3241Smlf  * In 48-bit extended mode, the sector count is 16 bits wide, and the
1777507c3241Smlf  * LBA is 48 bits wide, as follows:
1778507c3241Smlf  * register	most recent	previous
1779507c3241Smlf  * name		value		value
1780507c3241Smlf  * --------	----------	---------
1781507c3241Smlf  * sector cnt	count(7:0)	count(15:8)
1782507c3241Smlf  * sector num	lba(7:0)	lba(31:24)
1783507c3241Smlf  * cyl low	lba(15:8)	lba(39:32)
1784507c3241Smlf  * cyl hi	lba(23:16)	lba(47:40)
1785507c3241Smlf  * device/head	111D0000	N/A
1786507c3241Smlf  *               ^ ^
1787507c3241Smlf  *               | |
1788507c3241Smlf  *               | +-- drive number
1789507c3241Smlf  *               |
1790507c3241Smlf  *               +-- indicates LBA
1791507c3241Smlf  *	The other two 1 bits are historical and are not used in 48bit
1792507c3241Smlf  *	extended mode.
1793507c3241Smlf  */
1794507c3241Smlf /*
1795507c3241Smlf  * WARNING:
1796507c3241Smlf  * dada framework passes starting sector as daddr_t type, thus
1797507c3241Smlf  * limiting reachable disk space in 32-bit x86 architecture to 1 terabyte.
1798507c3241Smlf  * Therefore high 16 bits of the 48-bits address can be and
1799507c3241Smlf  * are currently ignored.
1800507c3241Smlf  */
1801507c3241Smlf static void
ata_disk_load_regs_lba48(ata_pkt_t * ata_pktp,ata_drv_t * ata_drvp)1802507c3241Smlf ata_disk_load_regs_lba48(ata_pkt_t *ata_pktp, ata_drv_t *ata_drvp)
1803507c3241Smlf {
1804507c3241Smlf 	ata_ctl_t	*ata_ctlp = ata_drvp->ad_ctlp;
1805507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
1806507c3241Smlf 	uint16_t	seccnt;		/* 16-bit sector count */
1807507c3241Smlf 	uint_t		lbalow;		/* low-order 24 bits of LBA */
1808507c3241Smlf 	uint_t		lbahi;		/* high-order 24 bits of LBA */
1809507c3241Smlf 
1810507c3241Smlf 	seccnt = ata_pktp->ap_count;
1811507c3241Smlf 	/* high-order 8 bits of lbalow never get used */
1812507c3241Smlf 	lbalow = ata_pktp->ap_startsec;
1813507c3241Smlf 	lbahi = ata_pktp->ap_startsec >> 24;
1814507c3241Smlf 
1815507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_count, seccnt >> 8);
1816507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_count, seccnt);
1817507c3241Smlf 	/* Send the high-order half first */
1818507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_sect, lbahi);
1819507c3241Smlf 	lbahi >>= 8;
1820507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_lcyl, lbahi);
1821507c3241Smlf 	lbahi >>= 8;
1822507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_hcyl, lbahi);
1823507c3241Smlf 	/* Send the low-order half */
1824507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_sect, lbalow);
1825507c3241Smlf 	lbalow >>= 8;
1826507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_lcyl, lbalow);
1827507c3241Smlf 	lbalow >>= 8;
1828507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_hcyl, lbalow);
1829*1bff1300SToomas Soome 	ddi_put8(io_hdl1,  ata_ctlp->ac_drvhd, ata_drvp->ad_drive_bits);
1830507c3241Smlf }
1831507c3241Smlf 
1832507c3241Smlf static void
ata_disk_load_regs_chs(ata_pkt_t * ata_pktp,ata_drv_t * ata_drvp)1833507c3241Smlf ata_disk_load_regs_chs(ata_pkt_t *ata_pktp, ata_drv_t *ata_drvp)
1834507c3241Smlf {
1835507c3241Smlf 	ata_ctl_t		*ata_ctlp = ata_drvp->ad_ctlp;
1836507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
1837507c3241Smlf 	uint_t			resid;
1838507c3241Smlf 	uint_t			cyl;
1839507c3241Smlf 	uchar_t			head;
1840507c3241Smlf 	uchar_t			drvheads;
1841507c3241Smlf 	uchar_t			drvsectors;
1842507c3241Smlf 
1843507c3241Smlf 	drvheads = ata_drvp->ad_phhd;
1844507c3241Smlf 	drvsectors = ata_drvp->ad_phsec;
1845507c3241Smlf 
1846507c3241Smlf 	resid = ata_pktp->ap_startsec / drvsectors;
1847507c3241Smlf 	head = (resid % drvheads) & 0xf;
1848507c3241Smlf 	cyl = resid / drvheads;
1849*1bff1300SToomas Soome 	/* automatically truncate to char */
1850507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_sect,
1851*1bff1300SToomas Soome 	    (ata_pktp->ap_startsec % drvsectors) + 1);
1852507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_count, ata_pktp->ap_count);
1853507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_hcyl, (cyl >> 8));
1854*1bff1300SToomas Soome 	/* lcyl gets truncated to 8 bits */
1855507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_lcyl, cyl);
1856*1bff1300SToomas Soome 	ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, ata_drvp->ad_drive_bits | head);
1857507c3241Smlf }
1858507c3241Smlf 
1859507c3241Smlf 
1860507c3241Smlf /*
1861507c3241Smlf  *
1862507c3241Smlf  * packet start callback routines
1863507c3241Smlf  *
1864507c3241Smlf  */
1865507c3241Smlf 
1866507c3241Smlf /* ARGSUSED */
1867507c3241Smlf static int
ata_disk_start_common(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)1868*1bff1300SToomas Soome ata_disk_start_common(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
1869*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
1870507c3241Smlf {
1871507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
1872507c3241Smlf 	ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
1873507c3241Smlf 
1874507c3241Smlf 	ADBG_TRACE(("ata_disk_start_common entered\n"));
1875507c3241Smlf 
1876507c3241Smlf 	ADBG_TRANSPORT(("ata_disk_start:\tpkt = 0x%p, pkt flags = 0x%x\n",
1877*1bff1300SToomas Soome 	    ata_pktp, ata_pktp->ap_flags));
1878507c3241Smlf 	ADBG_TRANSPORT(("\tcommand=0x%x, sect=0x%lx\n",
1879*1bff1300SToomas Soome 	    ata_pktp->ap_cmd, ata_pktp->ap_startsec));
1880507c3241Smlf 	ADBG_TRANSPORT(("\tcount=0x%x, drvhd = 0x%x\n",
1881*1bff1300SToomas Soome 	    ata_pktp->ap_count, ata_drvp->ad_drive_bits));
1882507c3241Smlf 
1883507c3241Smlf 	/*
1884507c3241Smlf 	 * If AC_BSY_WAIT is set, wait for controller to not be busy,
1885507c3241Smlf 	 * before issuing a command.  If AC_BSY_WAIT is not set,
1886507c3241Smlf 	 * skip the wait.  This is important for laptops that do
1887507c3241Smlf 	 * suspend/resume but do not correctly wait for the busy bit to
1888507c3241Smlf 	 * drop after a resume.
1889507c3241Smlf 	 *
1890507c3241Smlf 	 * NOTE: this test for ATS_BSY is also needed if/when we
1891507c3241Smlf 	 * implement the overlapped/queued command protocols. Currently,
1892507c3241Smlf 	 * the overlap/queued feature is not supported so the test is
1893507c3241Smlf 	 * conditional.
1894507c3241Smlf 	 */
1895507c3241Smlf 	if (ata_ctlp->ac_timing_flags & AC_BSY_WAIT) {
1896507c3241Smlf 		if (!ata_wait(io_hdl2,  ata_ctlp->ac_ioaddr2,
1897*1bff1300SToomas Soome 		    0, ATS_BSY, 5000000)) {
1898507c3241Smlf 			ADBG_ERROR(("ata_disk_start: BUSY\n"));
1899507c3241Smlf 			return (FALSE);
1900507c3241Smlf 		}
1901507c3241Smlf 	}
1902507c3241Smlf 
1903507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, ata_drvp->ad_drive_bits);
19049f49ae27Smlf 	ata_nsecwait(400);
1905507c3241Smlf 
1906507c3241Smlf 	/*
1907507c3241Smlf 	 * make certain the drive selected
1908507c3241Smlf 	 */
1909507c3241Smlf 	if (!ata_wait(io_hdl2,  ata_ctlp->ac_ioaddr2,
1910*1bff1300SToomas Soome 	    ATS_DRDY, ATS_BSY, 5 * 1000000)) {
1911507c3241Smlf 		ADBG_ERROR(("ata_disk_start: select failed\n"));
1912507c3241Smlf 		return (FALSE);
1913507c3241Smlf 	}
1914507c3241Smlf 
19150f2c99a4Syt 	if (ata_pktp->ap_cmd == ATC_LOAD_FW) {
19160f2c99a4Syt 
19170f2c99a4Syt 		/* the sector count is 16 bits wide */
19180f2c99a4Syt 		ddi_put8(io_hdl1, ata_ctlp->ac_count, ata_pktp->ap_count);
19190f2c99a4Syt 		ddi_put8(io_hdl1, ata_ctlp->ac_sect, ata_pktp->ap_count >> 8);
19200f2c99a4Syt 		ddi_put8(io_hdl1, ata_ctlp->ac_lcyl, ata_pktp->ap_startsec);
19210f2c99a4Syt 		ddi_put8(io_hdl1, ata_ctlp->ac_hcyl,
19220f2c99a4Syt 		    ata_pktp->ap_startsec >> 8);
19230f2c99a4Syt 
19240f2c99a4Syt 		/* put subcommand for DOWNLOAD MICROCODE */
19250f2c99a4Syt 		ddi_put8(io_hdl1, ata_ctlp->ac_feature, ata_pktp->ap_bcount);
19260f2c99a4Syt 	} else {
19270f2c99a4Syt 
19280f2c99a4Syt 		/*
19290f2c99a4Syt 		 * We use different methods for loading the task file
19300f2c99a4Syt 		 * registers, depending on whether the disk
19310f2c99a4Syt 		 * uses LBA or CHS addressing and whether 48-bit
19320f2c99a4Syt 		 * extended addressing is to be used.
19330f2c99a4Syt 		 */
19340f2c99a4Syt 		if (!(ata_drvp->ad_drive_bits & ATDH_LBA))
19350f2c99a4Syt 			ata_disk_load_regs_chs(ata_pktp, ata_drvp);
19360f2c99a4Syt 		else if (ata_drvp->ad_flags & AD_EXT48)
19370f2c99a4Syt 			ata_disk_load_regs_lba48(ata_pktp, ata_drvp);
19380f2c99a4Syt 		else
19390f2c99a4Syt 			ata_disk_load_regs_lba28(ata_pktp, ata_drvp);
19400f2c99a4Syt 		ddi_put8(io_hdl1, ata_ctlp->ac_feature, 0);
19410f2c99a4Syt 	}
1942507c3241Smlf 
1943507c3241Smlf 	/*
1944507c3241Smlf 	 * Always make certain interrupts are enabled. It's been reported
1945507c3241Smlf 	 * (but not confirmed) that some notebook computers don't
1946507c3241Smlf 	 * clear the interrupt disable bit after being resumed. The
1947507c3241Smlf 	 * easiest way to fix this is to always clear the disable bit
1948507c3241Smlf 	 * before every command.
1949507c3241Smlf 	 */
1950507c3241Smlf 	ddi_put8(io_hdl2, ata_ctlp->ac_devctl, ATDC_D3);
1951507c3241Smlf 	return (TRUE);
1952507c3241Smlf }
1953507c3241Smlf 
1954507c3241Smlf 
1955507c3241Smlf /*
1956507c3241Smlf  *
1957507c3241Smlf  * Start a non-data ATA command (not DMA and not PIO):
1958507c3241Smlf  *
1959507c3241Smlf  */
1960507c3241Smlf 
1961507c3241Smlf static int
ata_disk_start(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)1962*1bff1300SToomas Soome ata_disk_start(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
1963*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
1964507c3241Smlf {
1965507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
1966507c3241Smlf 	int		 rc;
1967507c3241Smlf 
1968507c3241Smlf 	rc = ata_disk_start_common(ata_ctlp, ata_drvp, ata_pktp);
1969507c3241Smlf 
1970507c3241Smlf 	if (!rc)
1971507c3241Smlf 		return (ATA_FSM_RC_BUSY);
1972507c3241Smlf 
1973507c3241Smlf 	/*
1974507c3241Smlf 	 * This next one sets the controller in motion
1975507c3241Smlf 	 */
1976507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_cmd, ata_pktp->ap_cmd);
1977507c3241Smlf 
1978507c3241Smlf 	/* wait for the busy bit to settle */
19799f49ae27Smlf 	ata_nsecwait(400);
1980507c3241Smlf 
1981507c3241Smlf 	return (ATA_FSM_RC_OKAY);
1982507c3241Smlf }
1983507c3241Smlf 
1984507c3241Smlf 
1985507c3241Smlf 
1986507c3241Smlf static int
ata_disk_start_dma_in(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)1987*1bff1300SToomas Soome ata_disk_start_dma_in(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
1988*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
1989507c3241Smlf {
1990507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
1991507c3241Smlf 	int		 rc;
1992507c3241Smlf 
1993507c3241Smlf 	rc = ata_disk_start_common(ata_ctlp, ata_drvp, ata_pktp);
1994507c3241Smlf 
1995507c3241Smlf 	if (!rc)
1996507c3241Smlf 		return (ATA_FSM_RC_BUSY);
1997507c3241Smlf 
1998507c3241Smlf 	/*
1999507c3241Smlf 	 * Copy the Scatter/Gather list to the controller's
2000507c3241Smlf 	 * Physical Region Descriptor Table
2001507c3241Smlf 	 */
2002507c3241Smlf 	ata_pciide_dma_setup(ata_ctlp, ata_pktp->ap_sg_list,
2003*1bff1300SToomas Soome 	    ata_pktp->ap_sg_cnt);
2004507c3241Smlf 
2005507c3241Smlf 	/*
2006507c3241Smlf 	 * reset the PCIIDE Controller's interrupt and error status bits
2007507c3241Smlf 	 */
2008507c3241Smlf 	(void) ata_pciide_status_clear(ata_ctlp);
2009507c3241Smlf 
2010507c3241Smlf 	/*
2011507c3241Smlf 	 * This next one sets the drive in motion
2012507c3241Smlf 	 */
2013507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_cmd, ata_pktp->ap_cmd);
2014507c3241Smlf 
2015507c3241Smlf 	/* wait for the drive's busy bit to settle */
20169f49ae27Smlf 	ata_nsecwait(400);
2017507c3241Smlf 
2018507c3241Smlf 	ata_pciide_dma_start(ata_ctlp, PCIIDE_BMICX_RWCON_WRITE_TO_MEMORY);
2019507c3241Smlf 
2020507c3241Smlf 	return (ATA_FSM_RC_OKAY);
2021507c3241Smlf }
2022507c3241Smlf 
2023507c3241Smlf 
2024507c3241Smlf 
2025507c3241Smlf static int
ata_disk_start_dma_out(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2026*1bff1300SToomas Soome ata_disk_start_dma_out(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
2027*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
2028507c3241Smlf {
2029507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2030507c3241Smlf 	int		 rc;
2031507c3241Smlf 
2032507c3241Smlf 	rc = ata_disk_start_common(ata_ctlp, ata_drvp, ata_pktp);
2033507c3241Smlf 
2034507c3241Smlf 	if (!rc)
2035507c3241Smlf 		return (ATA_FSM_RC_BUSY);
2036507c3241Smlf 
2037507c3241Smlf 	/*
2038507c3241Smlf 	 * Copy the Scatter/Gather list to the controller's
2039507c3241Smlf 	 * Physical Region Descriptor Table
2040507c3241Smlf 	 */
2041507c3241Smlf 	ata_pciide_dma_setup(ata_ctlp, ata_pktp->ap_sg_list,
2042*1bff1300SToomas Soome 	    ata_pktp->ap_sg_cnt);
2043507c3241Smlf 
2044507c3241Smlf 	/*
2045507c3241Smlf 	 * reset the PCIIDE Controller's interrupt and error status bits
2046507c3241Smlf 	 */
2047507c3241Smlf 	(void) ata_pciide_status_clear(ata_ctlp);
2048507c3241Smlf 
2049507c3241Smlf 	/*
2050507c3241Smlf 	 * This next one sets the drive in motion
2051507c3241Smlf 	 */
2052507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_cmd, ata_pktp->ap_cmd);
2053507c3241Smlf 
2054507c3241Smlf 	/* wait for the drive's busy bit to settle */
20559f49ae27Smlf 	ata_nsecwait(400);
2056507c3241Smlf 
2057507c3241Smlf 	ata_pciide_dma_start(ata_ctlp, PCIIDE_BMICX_RWCON_READ_FROM_MEMORY);
2058507c3241Smlf 
2059507c3241Smlf 	return (ATA_FSM_RC_OKAY);
2060507c3241Smlf }
2061507c3241Smlf 
2062507c3241Smlf 
2063507c3241Smlf 
2064507c3241Smlf 
2065507c3241Smlf 
2066507c3241Smlf /*
2067507c3241Smlf  *
2068507c3241Smlf  * Start a PIO data-in ATA command:
2069507c3241Smlf  *
2070507c3241Smlf  */
2071507c3241Smlf 
2072507c3241Smlf static int
ata_disk_start_pio_in(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2073507c3241Smlf ata_disk_start_pio_in(
2074507c3241Smlf 	ata_ctl_t *ata_ctlp,
2075507c3241Smlf 	ata_drv_t *ata_drvp,
2076507c3241Smlf 	ata_pkt_t *ata_pktp)
2077507c3241Smlf {
2078507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2079507c3241Smlf 	int		 rc;
2080507c3241Smlf 
2081507c3241Smlf 	rc = ata_disk_start_common(ata_ctlp, ata_drvp, ata_pktp);
2082507c3241Smlf 
2083507c3241Smlf 	if (!rc)
2084507c3241Smlf 		return (ATA_FSM_RC_BUSY);
2085507c3241Smlf 	/*
2086507c3241Smlf 	 * This next one sets the controller in motion
2087507c3241Smlf 	 */
2088507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_cmd, ata_pktp->ap_cmd);
2089507c3241Smlf 
2090507c3241Smlf 	/* wait for the busy bit to settle */
20919f49ae27Smlf 	ata_nsecwait(400);
2092507c3241Smlf 
2093507c3241Smlf 	return (ATA_FSM_RC_OKAY);
2094507c3241Smlf }
2095507c3241Smlf 
2096507c3241Smlf 
2097507c3241Smlf 
2098507c3241Smlf 
2099507c3241Smlf /*
2100507c3241Smlf  *
2101507c3241Smlf  * Start a PIO data-out ATA command:
2102507c3241Smlf  *
2103507c3241Smlf  */
2104507c3241Smlf 
2105507c3241Smlf static int
ata_disk_start_pio_out(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2106*1bff1300SToomas Soome ata_disk_start_pio_out(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
2107*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
2108507c3241Smlf {
2109507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2110507c3241Smlf 	ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
2111507c3241Smlf 	int		 rc;
2112507c3241Smlf 
2113507c3241Smlf 	ata_pktp->ap_wrt_count = 0;
2114507c3241Smlf 
2115507c3241Smlf 	rc = ata_disk_start_common(ata_ctlp, ata_drvp, ata_pktp);
2116507c3241Smlf 
2117507c3241Smlf 	if (!rc)
2118507c3241Smlf 		return (ATA_FSM_RC_BUSY);
2119507c3241Smlf 	/*
2120507c3241Smlf 	 * This next one sets the controller in motion
2121507c3241Smlf 	 */
2122507c3241Smlf 	ddi_put8(io_hdl1, ata_ctlp->ac_cmd, ata_pktp->ap_cmd);
2123507c3241Smlf 
2124507c3241Smlf 	/* wait for the busy bit to settle */
21259f49ae27Smlf 	ata_nsecwait(400);
2126507c3241Smlf 
2127507c3241Smlf 	/*
2128507c3241Smlf 	 * Wait for the drive to assert DRQ to send the first chunk
2129507c3241Smlf 	 * of data. Have to busy wait because there's no interrupt for
2130507c3241Smlf 	 * the first chunk. This sucks (a lot of cycles) if the
2131507c3241Smlf 	 * drive responds too slowly or if the wait loop granularity
2132507c3241Smlf 	 * is too large. It's really bad if the drive is defective and
2133507c3241Smlf 	 * the loop times out.
2134507c3241Smlf 	 */
2135507c3241Smlf 
2136507c3241Smlf 	if (!ata_wait3(io_hdl2, ata_ctlp->ac_ioaddr2,
2137*1bff1300SToomas Soome 	    ATS_DRQ, ATS_BSY, /* okay */
2138*1bff1300SToomas Soome 	    ATS_ERR, ATS_BSY, /* cmd failed */
2139*1bff1300SToomas Soome 	    ATS_DF, ATS_BSY, /* drive failed */
2140*1bff1300SToomas Soome 	    4000000)) {
2141507c3241Smlf 		ADBG_WARN(("ata_disk_start_pio_out: no DRQ\n"));
2142507c3241Smlf 		ata_pktp->ap_flags |= AP_ERROR;
2143507c3241Smlf 		return (ATA_FSM_RC_INTR);
2144507c3241Smlf 	}
2145507c3241Smlf 
2146507c3241Smlf 	/*
2147507c3241Smlf 	 * Tell the upper layer to fake a hardware interrupt which
2148507c3241Smlf 	 * actually causes the first segment to be written to the drive.
2149507c3241Smlf 	 */
2150507c3241Smlf 	return (ATA_FSM_RC_INTR);
2151507c3241Smlf }
2152507c3241Smlf 
2153507c3241Smlf 
2154507c3241Smlf 
2155507c3241Smlf /*
2156507c3241Smlf  *
2157507c3241Smlf  * packet complete callback routine
2158507c3241Smlf  *
2159507c3241Smlf  */
2160507c3241Smlf 
2161507c3241Smlf static void
ata_disk_complete(ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp,int do_callback)2162*1bff1300SToomas Soome ata_disk_complete(ata_drv_t *ata_drvp, ata_pkt_t *ata_pktp, int do_callback)
2163507c3241Smlf {
2164507c3241Smlf 	struct ata_id   *aidp = &ata_drvp->ad_id;
2165507c3241Smlf 	cmpkt_t	*pktp;
2166507c3241Smlf 
2167507c3241Smlf 	ADBG_TRACE(("ata_disk_complete entered\n"));
2168507c3241Smlf 	ADBG_TRANSPORT(("ata_disk_complete: pkt = 0x%p\n", ata_pktp));
2169507c3241Smlf 
2170507c3241Smlf 	pktp = APKT2CPKT(ata_pktp);
2171507c3241Smlf 
2172507c3241Smlf 	/* update resid */
2173507c3241Smlf 
2174507c3241Smlf 	pktp->cp_resid = ata_pktp->ap_resid;
2175507c3241Smlf 
2176507c3241Smlf 	if (ata_pktp->ap_flags & AP_ERROR) {
2177507c3241Smlf 
2178507c3241Smlf 		pktp->cp_reason = CPS_CHKERR;
2179507c3241Smlf 
2180507c3241Smlf 		if (ata_pktp->ap_error & ATE_BBK_ICRC) {
2181507c3241Smlf 			if (IS_ATA_VERSION_GE(aidp, 4))
2182507c3241Smlf 				ata_pktp->ap_scb = DERR_ICRC;
2183507c3241Smlf 			else
2184507c3241Smlf 				ata_pktp->ap_scb = DERR_BBK;
2185507c3241Smlf 		} else if (ata_pktp->ap_error & ATE_UNC)
2186507c3241Smlf 			ata_pktp->ap_scb = DERR_UNC;
2187507c3241Smlf 		else if (ata_pktp->ap_error & ATE_IDNF)
2188507c3241Smlf 			ata_pktp->ap_scb = DERR_IDNF;
2189507c3241Smlf 		else if (ata_pktp->ap_error & ATE_TKONF)
2190507c3241Smlf 			ata_pktp->ap_scb = DERR_TKONF;
2191507c3241Smlf 		else if (ata_pktp->ap_error & ATE_AMNF)
2192507c3241Smlf 			ata_pktp->ap_scb = DERR_AMNF;
2193507c3241Smlf 		else if (ata_pktp->ap_status & ATS_BSY)
2194507c3241Smlf 			ata_pktp->ap_scb = DERR_BUSY;
2195507c3241Smlf 		else if (ata_pktp->ap_status & ATS_DF)
2196507c3241Smlf 			ata_pktp->ap_scb = DERR_DWF;
2197507c3241Smlf 		else /* any unknown error	*/
2198507c3241Smlf 			ata_pktp->ap_scb = DERR_ABORT;
2199*1bff1300SToomas Soome 	} else if (ata_pktp->ap_flags & (AP_ABORT|AP_TIMEOUT|AP_BUS_RESET)) {
2200507c3241Smlf 
2201507c3241Smlf 		pktp->cp_reason = CPS_CHKERR;
2202507c3241Smlf 		ata_pktp->ap_scb = DERR_ABORT;
2203507c3241Smlf 	} else {
2204507c3241Smlf 		pktp->cp_reason = CPS_SUCCESS;
2205507c3241Smlf 		ata_pktp->ap_scb = DERR_SUCCESS;
2206507c3241Smlf 	}
2207507c3241Smlf 
2208507c3241Smlf 	/* callback */
2209507c3241Smlf 	if (do_callback)
2210507c3241Smlf 		(*pktp->cp_callback)(pktp);
2211507c3241Smlf }
2212507c3241Smlf 
2213507c3241Smlf 
2214507c3241Smlf /*
2215507c3241Smlf  *
2216507c3241Smlf  * Interrupt callbacks
2217507c3241Smlf  *
2218507c3241Smlf  */
2219507c3241Smlf 
2220507c3241Smlf 
2221507c3241Smlf /*
2222507c3241Smlf  *
2223507c3241Smlf  * ATA command, no data
2224507c3241Smlf  *
2225507c3241Smlf  */
2226507c3241Smlf 
2227507c3241Smlf /* ARGSUSED */
2228507c3241Smlf static int
ata_disk_intr(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2229*1bff1300SToomas Soome ata_disk_intr(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
2230*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
2231507c3241Smlf {
2232507c3241Smlf 	uchar_t		 status;
2233507c3241Smlf 
2234507c3241Smlf 	ADBG_TRACE(("ata_disk_intr entered\n"));
2235507c3241Smlf 	ADBG_TRANSPORT(("ata_disk_intr: pkt = 0x%p\n", ata_pktp));
2236507c3241Smlf 
2237507c3241Smlf 	status = ata_get_status_clear_intr(ata_ctlp, ata_pktp);
2238507c3241Smlf 
2239507c3241Smlf 	ASSERT((status & (ATS_BSY | ATS_DRQ)) == 0);
2240507c3241Smlf 
2241507c3241Smlf 	/*
2242507c3241Smlf 	 * check for errors
2243507c3241Smlf 	 */
2244507c3241Smlf 
2245507c3241Smlf 	if (status & (ATS_DF | ATS_ERR)) {
2246507c3241Smlf 		ADBG_WARN(("ata_disk_intr: status 0x%x error 0x%x\n", status,
2247*1bff1300SToomas Soome 		    ddi_get8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_error)));
2248507c3241Smlf 		ata_pktp->ap_flags |= AP_ERROR;
2249507c3241Smlf 	}
2250507c3241Smlf 
2251507c3241Smlf 	if (ata_pktp->ap_flags & AP_ERROR) {
2252507c3241Smlf 		ata_pktp->ap_status = ddi_get8(ata_ctlp->ac_iohandle2,
2253*1bff1300SToomas Soome 		    ata_ctlp->ac_altstatus);
2254507c3241Smlf 		ata_pktp->ap_error = ddi_get8(ata_ctlp->ac_iohandle1,
2255*1bff1300SToomas Soome 		    ata_ctlp->ac_error);
2256507c3241Smlf 	}
2257507c3241Smlf 
2258507c3241Smlf 	/* tell the upper layer this request is complete */
2259507c3241Smlf 	return (ATA_FSM_RC_FINI);
2260507c3241Smlf }
2261507c3241Smlf 
2262507c3241Smlf 
2263507c3241Smlf /*
2264507c3241Smlf  *
2265507c3241Smlf  * ATA command, PIO data in
2266507c3241Smlf  *
2267507c3241Smlf  */
2268507c3241Smlf 
2269507c3241Smlf /* ARGSUSED */
2270507c3241Smlf static int
ata_disk_intr_pio_in(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2271*1bff1300SToomas Soome ata_disk_intr_pio_in(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
2272*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
2273507c3241Smlf {
2274507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2275507c3241Smlf 	ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
2276507c3241Smlf 	uchar_t		 status;
2277507c3241Smlf 
2278507c3241Smlf 	ADBG_TRACE(("ata_disk_pio_in entered\n"));
2279507c3241Smlf 	ADBG_TRANSPORT(("ata_disk_pio_in: pkt = 0x%p\n", ata_pktp));
2280507c3241Smlf 
2281507c3241Smlf 	/*
2282507c3241Smlf 	 * first make certain DRQ is asserted (and no errors)
2283507c3241Smlf 	 */
2284507c3241Smlf 	(void) ata_wait3(io_hdl2, ata_ctlp->ac_ioaddr2,
2285*1bff1300SToomas Soome 	    ATS_DRQ, ATS_BSY, ATS_ERR, ATS_BSY, ATS_DF, ATS_BSY, 4000000);
2286507c3241Smlf 
2287507c3241Smlf 	status = ata_get_status_clear_intr(ata_ctlp, ata_pktp);
2288507c3241Smlf 
2289507c3241Smlf 	if (status & ATS_BSY) {
2290507c3241Smlf 		ADBG_WARN(("ata_disk_pio_in: BUSY\n"));
2291507c3241Smlf 		ata_pktp->ap_flags |= AP_ERROR;
2292507c3241Smlf 		ata_pktp->ap_status = ddi_get8(io_hdl2, ata_ctlp->ac_altstatus);
2293507c3241Smlf 		ata_pktp->ap_error = ddi_get8(io_hdl1, ata_ctlp->ac_error);
2294507c3241Smlf 		return (ATA_FSM_RC_BUSY);
2295507c3241Smlf 	}
2296507c3241Smlf 
2297507c3241Smlf 	/*
2298507c3241Smlf 	 * record any errors
2299507c3241Smlf 	 */
2300507c3241Smlf 	if ((status & (ATS_DRQ | ATS_DF | ATS_ERR)) != ATS_DRQ) {
2301507c3241Smlf 		ADBG_WARN(("ata_disk_pio_in: status 0x%x error 0x%x\n",
2302*1bff1300SToomas Soome 		    status, ddi_get8(io_hdl1, ata_ctlp->ac_error)));
2303507c3241Smlf 		ata_pktp->ap_flags |= AP_ERROR;
2304507c3241Smlf 		ata_pktp->ap_status = ddi_get8(io_hdl2, ata_ctlp->ac_altstatus);
2305507c3241Smlf 		ata_pktp->ap_error = ddi_get8(io_hdl1, ata_ctlp->ac_error);
2306507c3241Smlf 	}
2307507c3241Smlf 
2308507c3241Smlf 	/*
2309507c3241Smlf 	 * read the next chunk of data (if any)
2310507c3241Smlf 	 */
2311507c3241Smlf 	if (status & ATS_DRQ) {
2312507c3241Smlf 		ata_disk_pio_xfer_data_in(ata_ctlp, ata_pktp);
2313507c3241Smlf 	}
2314507c3241Smlf 
2315507c3241Smlf 	/*
2316507c3241Smlf 	 * If that was the last chunk, wait for the device to clear DRQ
2317507c3241Smlf 	 */
2318507c3241Smlf 	if (ata_pktp->ap_resid == 0) {
2319507c3241Smlf 		if (ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2,
2320*1bff1300SToomas Soome 		    0, (ATS_DRQ | ATS_BSY), 4000000)) {
2321507c3241Smlf 			/* tell the upper layer this request is complete */
2322507c3241Smlf 			return (ATA_FSM_RC_FINI);
2323507c3241Smlf 		}
2324507c3241Smlf 
2325507c3241Smlf 		ADBG_WARN(("ata_disk_pio_in: DRQ stuck\n"));
2326507c3241Smlf 		ata_pktp->ap_flags |= AP_ERROR;
2327507c3241Smlf 		ata_pktp->ap_status = ddi_get8(io_hdl2, ata_ctlp->ac_altstatus);
2328507c3241Smlf 		ata_pktp->ap_error = ddi_get8(io_hdl1, ata_ctlp->ac_error);
2329507c3241Smlf 	}
2330507c3241Smlf 
2331507c3241Smlf 	/*
2332507c3241Smlf 	 * check for errors
2333507c3241Smlf 	 */
2334507c3241Smlf 	if (ata_pktp->ap_flags & AP_ERROR) {
2335507c3241Smlf 		return (ATA_FSM_RC_FINI);
2336507c3241Smlf 	}
2337507c3241Smlf 
2338507c3241Smlf 	/*
2339507c3241Smlf 	 * If the read command isn't done yet,
2340507c3241Smlf 	 * wait for the next interrupt.
2341507c3241Smlf 	 */
2342507c3241Smlf 	ADBG_TRACE(("ata_disk_pio_in: partial\n"));
2343507c3241Smlf 	return (ATA_FSM_RC_OKAY);
2344507c3241Smlf }
2345507c3241Smlf 
2346507c3241Smlf 
2347507c3241Smlf 
2348507c3241Smlf /*
2349507c3241Smlf  *
2350507c3241Smlf  * ATA command, PIO data out
2351507c3241Smlf  *
2352507c3241Smlf  */
2353507c3241Smlf 
2354507c3241Smlf /* ARGSUSED */
2355507c3241Smlf static int
ata_disk_intr_pio_out(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2356*1bff1300SToomas Soome ata_disk_intr_pio_out(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
2357*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
2358507c3241Smlf {
2359507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2360507c3241Smlf 	ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
2361507c3241Smlf 	int		 tmp_count = ata_pktp->ap_wrt_count;
2362507c3241Smlf 	uchar_t		 status;
2363507c3241Smlf 
2364507c3241Smlf 	/*
2365507c3241Smlf 	 * clear the IRQ
2366507c3241Smlf 	 */
2367507c3241Smlf 	status = ata_get_status_clear_intr(ata_ctlp, ata_pktp);
2368507c3241Smlf 
2369507c3241Smlf 	ADBG_TRACE(("ata_disk_intr_pio_out entered\n"));
2370507c3241Smlf 	ADBG_TRANSPORT(("ata_disk_intr_pio_out: pkt = 0x%p\n", ata_pktp));
2371507c3241Smlf 
2372507c3241Smlf 	ASSERT(!(status & ATS_BSY));
2373507c3241Smlf 
2374507c3241Smlf 
2375507c3241Smlf 	/*
2376507c3241Smlf 	 * check for errors
2377507c3241Smlf 	 */
2378507c3241Smlf 
2379507c3241Smlf 	if (status & (ATS_DF | ATS_ERR)) {
2380507c3241Smlf 		ADBG_WARN(("ata_disk_intr_pio_out: status 0x%x error 0x%x\n",
2381*1bff1300SToomas Soome 		    status, ddi_get8(io_hdl1, ata_ctlp->ac_error)));
2382507c3241Smlf 		ata_pktp->ap_flags |= AP_ERROR;
2383507c3241Smlf 		ata_pktp->ap_status = ddi_get8(io_hdl2, ata_ctlp->ac_altstatus);
2384507c3241Smlf 		ata_pktp->ap_error = ddi_get8(io_hdl1, ata_ctlp->ac_error);
2385507c3241Smlf 		/* tell the upper layer this request is complete */
2386507c3241Smlf 		return (ATA_FSM_RC_FINI);
2387507c3241Smlf 	}
2388507c3241Smlf 
2389507c3241Smlf 
2390507c3241Smlf 	/*
2391507c3241Smlf 	 * last write was okay, bump the ptr and
2392507c3241Smlf 	 * decr the resid count
2393507c3241Smlf 	 */
2394507c3241Smlf 	ata_pktp->ap_v_addr += tmp_count;
2395507c3241Smlf 	ata_pktp->ap_resid -= tmp_count;
2396507c3241Smlf 
2397507c3241Smlf 	/*
2398507c3241Smlf 	 * check for final interrupt on write command
2399507c3241Smlf 	 */
2400f304523cSzhongyan gu - Sun Microsystems - Beijing China 	if (ata_pktp->ap_resid == 0) {
2401507c3241Smlf 		/* tell the upper layer this request is complete */
2402507c3241Smlf 		return (ATA_FSM_RC_FINI);
2403507c3241Smlf 	}
2404507c3241Smlf 
2405507c3241Smlf 	/*
2406507c3241Smlf 	 * Perform the next data transfer
2407507c3241Smlf 	 *
2408507c3241Smlf 	 * First make certain DRQ is asserted and no error status.
2409507c3241Smlf 	 * (I'm not certain but I think some drives might deassert BSY
2410507c3241Smlf 	 * before asserting DRQ. This extra ata_wait3() will
2411507c3241Smlf 	 * compensate for such drives).
2412507c3241Smlf 	 *
2413507c3241Smlf 	 */
2414507c3241Smlf 	(void) ata_wait3(io_hdl2, ata_ctlp->ac_ioaddr2,
2415*1bff1300SToomas Soome 	    ATS_DRQ, ATS_BSY, ATS_ERR, ATS_BSY, ATS_DF, ATS_BSY, 4000000);
2416507c3241Smlf 
2417507c3241Smlf 	status = ddi_get8(io_hdl2, ata_ctlp->ac_altstatus);
2418507c3241Smlf 
2419507c3241Smlf 	if (status & ATS_BSY) {
2420507c3241Smlf 		/* this should never happen */
2421507c3241Smlf 		ADBG_WARN(("ata_disk_intr_pio_out: BUSY\n"));
2422507c3241Smlf 		ata_pktp->ap_flags |= AP_ERROR;
2423507c3241Smlf 		ata_pktp->ap_status = ddi_get8(io_hdl2, ata_ctlp->ac_altstatus);
2424507c3241Smlf 		ata_pktp->ap_error = ddi_get8(io_hdl1, ata_ctlp->ac_error);
2425507c3241Smlf 		return (ATA_FSM_RC_BUSY);
2426507c3241Smlf 	}
2427507c3241Smlf 
2428507c3241Smlf 	/*
2429507c3241Smlf 	 * bailout if any errors
2430507c3241Smlf 	 */
2431507c3241Smlf 	if ((status & (ATS_DRQ | ATS_DF | ATS_ERR)) != ATS_DRQ) {
2432507c3241Smlf 		ADBG_WARN(("ata_disk_pio_out: status 0x%x error 0x%x\n",
2433*1bff1300SToomas Soome 		    status, ddi_get8(io_hdl1, ata_ctlp->ac_error)));
2434507c3241Smlf 		ata_pktp->ap_flags |= AP_ERROR;
2435507c3241Smlf 		ata_pktp->ap_status = ddi_get8(io_hdl2, ata_ctlp->ac_altstatus);
2436507c3241Smlf 		ata_pktp->ap_error = ddi_get8(io_hdl1, ata_ctlp->ac_error);
2437507c3241Smlf 		return (ATA_FSM_RC_FINI);
2438507c3241Smlf 	}
2439507c3241Smlf 
2440507c3241Smlf 	/*
2441507c3241Smlf 	 * write  the next chunk of data
2442507c3241Smlf 	 */
2443507c3241Smlf 	ADBG_TRACE(("ata_disk_intr_pio_out: write xfer\n"));
2444507c3241Smlf 	ata_disk_pio_xfer_data_out(ata_ctlp, ata_pktp);
2445507c3241Smlf 
2446507c3241Smlf 	/*
2447507c3241Smlf 	 * Wait for the next interrupt before checking the transfer
2448507c3241Smlf 	 * status and adjusting the transfer count.
2449507c3241Smlf 	 *
2450507c3241Smlf 	 */
2451507c3241Smlf 	return (ATA_FSM_RC_OKAY);
2452507c3241Smlf }
2453507c3241Smlf 
2454507c3241Smlf 
2455507c3241Smlf /*
2456507c3241Smlf  *
2457507c3241Smlf  * ATA command, DMA data in/out
2458507c3241Smlf  *
2459507c3241Smlf  */
2460507c3241Smlf 
2461507c3241Smlf static int
ata_disk_intr_dma(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2462*1bff1300SToomas Soome ata_disk_intr_dma(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp, ata_pkt_t *ata_pktp)
2463507c3241Smlf {
2464507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2465507c3241Smlf 	ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
2466507c3241Smlf 	uchar_t		 status;
2467507c3241Smlf 
2468507c3241Smlf 	ADBG_TRACE(("ata_disk_intr_dma entered\n"));
2469507c3241Smlf 	ADBG_TRANSPORT(("ata_disk_intr_dma: pkt = 0x%p\n", ata_pktp));
2470507c3241Smlf 
2471507c3241Smlf 	/*
2472507c3241Smlf 	 * halt the DMA engine
2473507c3241Smlf 	 */
2474507c3241Smlf 	ata_pciide_dma_stop(ata_ctlp);
2475507c3241Smlf 
2476507c3241Smlf 	/*
2477507c3241Smlf 	 * wait for the device to clear DRQ
2478507c3241Smlf 	 */
2479507c3241Smlf 	if (!ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2,
2480*1bff1300SToomas Soome 	    0, (ATS_DRQ | ATS_BSY), 4000000)) {
2481507c3241Smlf 		ADBG_WARN(("ata_disk_intr_dma: DRQ stuck\n"));
2482507c3241Smlf 		ata_pktp->ap_flags |= AP_ERROR;
2483507c3241Smlf 		ata_pktp->ap_status = ddi_get8(io_hdl2, ata_ctlp->ac_altstatus);
2484507c3241Smlf 		ata_pktp->ap_error = ddi_get8(io_hdl1, ata_ctlp->ac_error);
2485507c3241Smlf 		return (ATA_FSM_RC_BUSY);
2486507c3241Smlf 	}
2487507c3241Smlf 
2488507c3241Smlf 	/*
2489507c3241Smlf 	 * get the status and clear the IRQ, and check for DMA error
2490507c3241Smlf 	 */
2491507c3241Smlf 	status = ata_get_status_clear_intr(ata_ctlp, ata_pktp);
2492507c3241Smlf 
2493507c3241Smlf 	/*
2494507c3241Smlf 	 * check for drive errors
2495507c3241Smlf 	 */
2496507c3241Smlf 
2497507c3241Smlf 	if (status & (ATS_DF | ATS_ERR)) {
2498507c3241Smlf 		ADBG_WARN(("ata_disk_intr_dma: status 0x%x error 0x%x\n",
2499*1bff1300SToomas Soome 		    status, ddi_get8(io_hdl1, ata_ctlp->ac_error)));
2500507c3241Smlf 		ata_pktp->ap_flags |= AP_ERROR;
2501507c3241Smlf 		ata_pktp->ap_status = ddi_get8(io_hdl2, ata_ctlp->ac_altstatus);
2502507c3241Smlf 		ata_pktp->ap_error = ddi_get8(io_hdl1, ata_ctlp->ac_error);
2503507c3241Smlf 	}
2504507c3241Smlf 
2505507c3241Smlf 	/*
2506507c3241Smlf 	 * If there was a drive or DMA error, compute a resid count
2507507c3241Smlf 	 */
2508507c3241Smlf 	if (ata_pktp->ap_flags & AP_ERROR) {
2509507c3241Smlf 		/*
2510507c3241Smlf 		 * grab the last sector address from the drive regs
2511507c3241Smlf 		 * and use that to compute the resid
2512507c3241Smlf 		 */
2513507c3241Smlf 		ata_disk_get_resid(ata_ctlp, ata_drvp, ata_pktp);
2514507c3241Smlf 	} else {
2515507c3241Smlf 		ata_pktp->ap_resid = 0;
2516507c3241Smlf 	}
2517507c3241Smlf 
2518507c3241Smlf 	/* tell the upper layer this request is complete */
2519507c3241Smlf 	return (ATA_FSM_RC_FINI);
2520507c3241Smlf }
2521507c3241Smlf 
2522507c3241Smlf 
2523507c3241Smlf /*
2524507c3241Smlf  *
2525507c3241Smlf  * Low level PIO routine that transfers data from the drive
2526507c3241Smlf  *
2527507c3241Smlf  */
2528507c3241Smlf 
2529507c3241Smlf static void
ata_disk_pio_xfer_data_in(ata_ctl_t * ata_ctlp,ata_pkt_t * ata_pktp)2530*1bff1300SToomas Soome ata_disk_pio_xfer_data_in(ata_ctl_t *ata_ctlp, ata_pkt_t *ata_pktp)
2531507c3241Smlf {
2532507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2533507c3241Smlf 	int		 count;
2534507c3241Smlf 
2535*1bff1300SToomas Soome 	count = min(ata_pktp->ap_resid, ata_pktp->ap_bytes_per_block);
2536507c3241Smlf 
2537507c3241Smlf 	ADBG_TRANSPORT(("ata_disk_pio_xfer_data_in: 0x%x bytes, addr = 0x%p\n",
2538*1bff1300SToomas Soome 	    count, ata_pktp->ap_v_addr));
2539507c3241Smlf 
2540507c3241Smlf 	/*
2541507c3241Smlf 	 * read count bytes
2542507c3241Smlf 	 */
2543507c3241Smlf 
2544507c3241Smlf 	ASSERT(count != 0);
2545507c3241Smlf 
2546507c3241Smlf 	ddi_rep_get16(io_hdl1, (ushort_t *)ata_pktp->ap_v_addr,
2547*1bff1300SToomas Soome 	    ata_ctlp->ac_data, (count >> 1), DDI_DEV_NO_AUTOINCR);
2548507c3241Smlf 
2549507c3241Smlf 	/* wait for the busy bit to settle */
25509f49ae27Smlf 	ata_nsecwait(400);
2551507c3241Smlf 
2552507c3241Smlf 	/*
2553507c3241Smlf 	 * this read command completed okay, bump the ptr and
2554507c3241Smlf 	 * decr the resid count now.
2555507c3241Smlf 	 */
2556507c3241Smlf 	ata_pktp->ap_v_addr += count;
2557507c3241Smlf 	ata_pktp->ap_resid -= count;
2558507c3241Smlf }
2559507c3241Smlf 
2560507c3241Smlf 
2561507c3241Smlf /*
2562507c3241Smlf  *
2563507c3241Smlf  * Low level PIO routine that transfers data to the drive
2564507c3241Smlf  *
2565507c3241Smlf  */
2566507c3241Smlf 
2567507c3241Smlf static void
ata_disk_pio_xfer_data_out(ata_ctl_t * ata_ctlp,ata_pkt_t * ata_pktp)2568*1bff1300SToomas Soome ata_disk_pio_xfer_data_out(ata_ctl_t *ata_ctlp, ata_pkt_t *ata_pktp)
2569507c3241Smlf {
2570507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2571507c3241Smlf 	int		 count;
2572507c3241Smlf 
2573*1bff1300SToomas Soome 	count = min(ata_pktp->ap_resid, ata_pktp->ap_bytes_per_block);
2574507c3241Smlf 
2575507c3241Smlf 	ADBG_TRANSPORT(("ata_disk_pio_xfer_data_out: 0x%x bytes, addr = 0x%p\n",
2576*1bff1300SToomas Soome 	    count, ata_pktp->ap_v_addr));
2577507c3241Smlf 
2578507c3241Smlf 	/*
2579507c3241Smlf 	 * read or write count bytes
2580507c3241Smlf 	 */
2581507c3241Smlf 
2582507c3241Smlf 	ASSERT(count != 0);
2583507c3241Smlf 
2584507c3241Smlf 	ddi_rep_put16(io_hdl1, (ushort_t *)ata_pktp->ap_v_addr,
2585*1bff1300SToomas Soome 	    ata_ctlp->ac_data, (count >> 1), DDI_DEV_NO_AUTOINCR);
2586507c3241Smlf 
2587507c3241Smlf 	/* wait for the busy bit to settle */
25889f49ae27Smlf 	ata_nsecwait(400);
2589507c3241Smlf 
2590507c3241Smlf 	/*
2591507c3241Smlf 	 * save the count here so I can correctly adjust
2592507c3241Smlf 	 * the ap_v_addr and ap_resid values at the next
2593507c3241Smlf 	 * interrupt.
2594507c3241Smlf 	 */
2595507c3241Smlf 	ata_pktp->ap_wrt_count = count;
2596507c3241Smlf }
2597507c3241Smlf 
2598507c3241Smlf 
2599507c3241Smlf /*
2600507c3241Smlf  *
2601507c3241Smlf  * ATA Initialize Device Parameters (aka Set Params) command
2602507c3241Smlf  *
2603507c3241Smlf  * If the drive was put in some sort of CHS extended/logical geometry
2604507c3241Smlf  * mode by the BIOS, this function will reset it to its "native"
2605507c3241Smlf  * CHS geometry. This ensures that we don't run into any sort of
2606507c3241Smlf  * 1024 cylinder (or 65535 cylinder) limitation that may have been
2607507c3241Smlf  * created by a BIOS (or users) that chooses a bogus translated geometry.
2608507c3241Smlf  */
2609507c3241Smlf 
2610507c3241Smlf static int
ata_disk_initialize_device_parameters(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp)2611*1bff1300SToomas Soome ata_disk_initialize_device_parameters(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp)
2612507c3241Smlf {
2613507c3241Smlf 	int		 rc;
2614507c3241Smlf 
2615507c3241Smlf 	rc = ata_command(ata_ctlp, ata_drvp, FALSE, FALSE,
2616*1bff1300SToomas Soome 	    ata_disk_init_dev_parm_wait,
2617*1bff1300SToomas Soome 	    ATC_SETPARAM,
2618*1bff1300SToomas Soome 	    0,			/* feature n/a */
2619*1bff1300SToomas Soome 	    ata_drvp->ad_phsec,	/* max sector (1-based) */
2620*1bff1300SToomas Soome 	    0,			/* sector n/a */
2621*1bff1300SToomas Soome 	    (ata_drvp->ad_phhd -1),	/* max head (0-based) */
2622*1bff1300SToomas Soome 	    0,			/* cyl_low n/a */
2623*1bff1300SToomas Soome 	    0);			/* cyl_hi n/a */
2624507c3241Smlf 
2625ae115bc7Smrj 	if (rc)
2626507c3241Smlf 		return (TRUE);
2627507c3241Smlf 
2628507c3241Smlf 	ADBG_ERROR(("ata_init_dev_parms: failed\n"));
2629507c3241Smlf 	return (FALSE);
2630507c3241Smlf }
2631507c3241Smlf 
2632507c3241Smlf 
2633507c3241Smlf 
2634507c3241Smlf /*
2635507c3241Smlf  *
2636507c3241Smlf  * create fake inquiry data for DADA interface
2637507c3241Smlf  *
2638507c3241Smlf  */
2639507c3241Smlf 
2640507c3241Smlf static void
ata_disk_fake_inquiry(ata_drv_t * ata_drvp)2641*1bff1300SToomas Soome ata_disk_fake_inquiry(ata_drv_t *ata_drvp)
2642507c3241Smlf {
2643507c3241Smlf 	struct ata_id *ata_idp = &ata_drvp->ad_id;
2644507c3241Smlf 	struct scsi_inquiry *inqp = &ata_drvp->ad_inquiry;
2645507c3241Smlf 
2646507c3241Smlf 	ADBG_TRACE(("ata_disk_fake_inquiry entered\n"));
2647507c3241Smlf 
2648507c3241Smlf 	if (ata_idp->ai_config & ATA_ID_REM_DRV) /* ide removable bit */
2649507c3241Smlf 		inqp->inq_rmb = 1;		/* scsi removable bit */
2650507c3241Smlf 
2651507c3241Smlf 	(void) strncpy(inqp->inq_vid, "Gen-ATA ", sizeof (inqp->inq_vid));
2652507c3241Smlf 	inqp->inq_dtype = DTYPE_DIRECT;
2653507c3241Smlf 	inqp->inq_qual = DPQ_POSSIBLE;
2654507c3241Smlf 
2655507c3241Smlf 	(void) strncpy(inqp->inq_pid, ata_idp->ai_model,
2656*1bff1300SToomas Soome 	    sizeof (inqp->inq_pid));
2657507c3241Smlf 	(void) strncpy(inqp->inq_revision, ata_idp->ai_fw,
2658*1bff1300SToomas Soome 	    sizeof (inqp->inq_revision));
2659507c3241Smlf }
2660507c3241Smlf 
2661507c3241Smlf #define	LOOP_COUNT	10000
2662507c3241Smlf 
2663507c3241Smlf 
2664507c3241Smlf /*
2665507c3241Smlf  *
2666507c3241Smlf  * ATA Set Multiple Mode
2667507c3241Smlf  *
2668507c3241Smlf  */
2669507c3241Smlf 
2670507c3241Smlf static int
ata_disk_set_multiple(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp)2671*1bff1300SToomas Soome ata_disk_set_multiple(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp)
2672507c3241Smlf {
2673507c3241Smlf 	int		 rc;
2674507c3241Smlf 
2675507c3241Smlf 	rc = ata_command(ata_ctlp, ata_drvp, TRUE, FALSE,
2676*1bff1300SToomas Soome 	    ata_disk_set_mult_wait,
2677*1bff1300SToomas Soome 	    ATC_SETMULT,
2678*1bff1300SToomas Soome 	    0,			/* feature n/a */
2679*1bff1300SToomas Soome 	    ata_drvp->ad_block_factor, /* count */
2680*1bff1300SToomas Soome 	    0,			/* sector n/a */
2681*1bff1300SToomas Soome 	    0,			/* head n/a */
2682*1bff1300SToomas Soome 	    0,			/* cyl_low n/a */
2683*1bff1300SToomas Soome 	    0);			/* cyl_hi n/a */
2684507c3241Smlf 
2685507c3241Smlf 	if (rc) {
2686507c3241Smlf 		return (TRUE);
2687507c3241Smlf 	}
2688507c3241Smlf 
2689507c3241Smlf 	ADBG_ERROR(("ata_disk_set_multiple: failed\n"));
2690507c3241Smlf 	return (FALSE);
2691507c3241Smlf }
2692507c3241Smlf 
2693507c3241Smlf 
2694507c3241Smlf /*
2695507c3241Smlf  *
2696507c3241Smlf  * ATA Identify Device command
2697507c3241Smlf  *
2698507c3241Smlf  */
2699507c3241Smlf 
2700507c3241Smlf int
ata_disk_id(ddi_acc_handle_t io_hdl1,caddr_t ioaddr1,ddi_acc_handle_t io_hdl2,caddr_t ioaddr2,struct ata_id * ata_idp)2701*1bff1300SToomas Soome ata_disk_id(ddi_acc_handle_t io_hdl1, caddr_t ioaddr1, ddi_acc_handle_t io_hdl2,
2702*1bff1300SToomas Soome     caddr_t ioaddr2, struct ata_id *ata_idp)
2703507c3241Smlf {
2704507c3241Smlf 	int	rc;
2705507c3241Smlf 
2706507c3241Smlf 	ADBG_TRACE(("ata_disk_id entered\n"));
2707507c3241Smlf 
2708507c3241Smlf 	rc = ata_id_common(ATC_ID_DEVICE, TRUE, io_hdl1, ioaddr1, io_hdl2,
2709*1bff1300SToomas Soome 	    ioaddr2, ata_idp);
2710507c3241Smlf 
2711507c3241Smlf 	if (!rc)
2712507c3241Smlf 		return (FALSE);
2713507c3241Smlf 
2714507c3241Smlf 	/*
2715507c3241Smlf 	 * If the disk is a CF/Microdrive that works under ATA mode
2716507c3241Smlf 	 * through CF<->ATA adapters, identify it as an ATA device
2717507c3241Smlf 	 * and a non removable media.
2718507c3241Smlf 	 */
2719507c3241Smlf 	if (ata_idp->ai_config == ATA_ID_COMPACT_FLASH) {
2720507c3241Smlf 		ata_idp->ai_config = ATA_ID_CF_TO_ATA;
2721507c3241Smlf 	}
2722507c3241Smlf 
2723507c3241Smlf 	if ((ata_idp->ai_config & ATAC_ATA_TYPE_MASK) != ATAC_ATA_TYPE)
2724507c3241Smlf 		return (FALSE);
2725507c3241Smlf 
2726507c3241Smlf 	if (ata_idp->ai_heads == 0 || ata_idp->ai_sectors == 0) {
2727507c3241Smlf 		return (FALSE);
2728507c3241Smlf 	}
2729507c3241Smlf 
2730507c3241Smlf 	return (TRUE);
2731507c3241Smlf }
2732507c3241Smlf 
2733507c3241Smlf static daddr_t
ata_last_block_xferred_chs(ata_drv_t * ata_drvp)2734507c3241Smlf ata_last_block_xferred_chs(ata_drv_t *ata_drvp)
2735507c3241Smlf {
2736507c3241Smlf 	ata_ctl_t	*ata_ctlp = ata_drvp->ad_ctlp;
2737507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2738507c3241Smlf 	uchar_t		 drvheads = ata_drvp->ad_phhd;
2739507c3241Smlf 	uchar_t		 drvsectors = ata_drvp->ad_phsec;
2740507c3241Smlf 	uchar_t		 sector;
2741507c3241Smlf 	uchar_t		 head;
2742507c3241Smlf 	uchar_t		 low_cyl;
2743507c3241Smlf 	uchar_t		 hi_cyl;
2744507c3241Smlf 	daddr_t		 lbastop;
2745507c3241Smlf 
2746507c3241Smlf 	sector = ddi_get8(io_hdl1, ata_ctlp->ac_sect);
2747507c3241Smlf 	head = ddi_get8(io_hdl1, ata_ctlp->ac_drvhd) & 0xf;
2748507c3241Smlf 	low_cyl = ddi_get8(io_hdl1, ata_ctlp->ac_lcyl);
2749507c3241Smlf 	hi_cyl = ddi_get8(io_hdl1, ata_ctlp->ac_hcyl);
2750507c3241Smlf 
2751507c3241Smlf 	lbastop = low_cyl;
2752507c3241Smlf 	lbastop |= (uint_t)hi_cyl << 8;
2753507c3241Smlf 	lbastop *= (uint_t)drvheads;
2754507c3241Smlf 	lbastop += (uint_t)head;
2755507c3241Smlf 	lbastop *= (uint_t)drvsectors;
2756507c3241Smlf 	lbastop += (uint_t)sector - 1;
2757507c3241Smlf 	return (lbastop);
2758507c3241Smlf }
2759507c3241Smlf 
2760507c3241Smlf static daddr_t
ata_last_block_xferred_lba28(ata_ctl_t * ata_ctlp)2761507c3241Smlf ata_last_block_xferred_lba28(ata_ctl_t *ata_ctlp)
2762507c3241Smlf {
2763507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2764507c3241Smlf 	daddr_t		lbastop;
2765507c3241Smlf 
2766507c3241Smlf 	lbastop = ddi_get8(io_hdl1, ata_ctlp->ac_drvhd) & 0xf;
2767507c3241Smlf 	lbastop <<= 8;
2768507c3241Smlf 	lbastop += ddi_get8(io_hdl1, ata_ctlp->ac_hcyl);
2769507c3241Smlf 	lbastop <<= 8;
2770507c3241Smlf 	lbastop += ddi_get8(io_hdl1, ata_ctlp->ac_lcyl);
2771507c3241Smlf 	lbastop <<= 8;
2772507c3241Smlf 	lbastop += ddi_get8(io_hdl1, ata_ctlp->ac_sect);
2773507c3241Smlf 	return (lbastop);
2774507c3241Smlf }
2775507c3241Smlf 
2776507c3241Smlf static daddr_t
ata_last_block_xferred_lba48(ata_ctl_t * ata_ctlp)2777507c3241Smlf ata_last_block_xferred_lba48(ata_ctl_t *ata_ctlp)
2778507c3241Smlf {
2779507c3241Smlf 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2780507c3241Smlf 	ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
2781507c3241Smlf 	daddr_t		lbastop;
2782507c3241Smlf 
2783507c3241Smlf 	/* turn on HOB and read the high-order 24 bits */
2784507c3241Smlf 	ddi_put8(io_hdl2, ata_ctlp->ac_devctl, (ATDC_D3 | ATDC_HOB));
2785507c3241Smlf 	lbastop = ddi_get8(io_hdl1, ata_ctlp->ac_hcyl);
2786507c3241Smlf 	lbastop <<= 8;
2787507c3241Smlf 	lbastop += ddi_get8(io_hdl1, ata_ctlp->ac_lcyl);
2788507c3241Smlf 	lbastop <<= 8;
2789507c3241Smlf 	lbastop += ddi_get8(io_hdl1, ata_ctlp->ac_sect);
2790507c3241Smlf 	lbastop <<= 8;
2791507c3241Smlf 
2792507c3241Smlf 	/* Turn off HOB and read the low-order 24-bits */
2793507c3241Smlf 	ddi_put8(io_hdl2, ata_ctlp->ac_devctl, (ATDC_D3));
2794507c3241Smlf 	lbastop += ddi_get8(io_hdl1, ata_ctlp->ac_hcyl);
2795507c3241Smlf 	lbastop <<= 8;
2796507c3241Smlf 	lbastop += ddi_get8(io_hdl1, ata_ctlp->ac_lcyl);
2797507c3241Smlf 	lbastop <<= 8;
2798507c3241Smlf 	lbastop += ddi_get8(io_hdl1, ata_ctlp->ac_sect);
2799507c3241Smlf 	return (lbastop);
2800507c3241Smlf }
2801507c3241Smlf 
2802507c3241Smlf 
2803507c3241Smlf /*
2804507c3241Smlf  *
2805507c3241Smlf  * Need to compute a value for ap_resid so that cp_resid can
2806507c3241Smlf  * be set by ata_disk_complete(). The cp_resid var is actually
2807507c3241Smlf  * misnamed. It's actually the offset to the block in which the
2808507c3241Smlf  * error occurred not the number of bytes transferred to the device.
2809507c3241Smlf  * At least that's how dadk actually uses the cp_resid when reporting
2810507c3241Smlf  * an error. In other words the sector that had the error and the
2811507c3241Smlf  * number of bytes transferred don't always indicate the same offset.
2812507c3241Smlf  * On top of that, when doing DMA transfers there's actually no
2813507c3241Smlf  * way to determine how many bytes have been transferred by the DMA
2814507c3241Smlf  * engine. On the other hand, the drive will report which sector
2815507c3241Smlf  * it faulted on. Using that address this routine computes the
2816507c3241Smlf  * number of residual bytes beyond that point which probably weren't
2817507c3241Smlf  * written to the drive (the drive is allowed to re-order sector
2818507c3241Smlf  * writes but on an ATA disk there's no way to deal with that
2819507c3241Smlf  * complication; in other words, the resid value calculated by
2820507c3241Smlf  * this routine is as good as we can manage).
2821507c3241Smlf  */
2822507c3241Smlf 
2823507c3241Smlf static void
ata_disk_get_resid(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2824*1bff1300SToomas Soome ata_disk_get_resid(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
2825*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
2826507c3241Smlf {
2827507c3241Smlf 	uint_t		 lba_start;
2828507c3241Smlf 	uint_t		 lba_stop;
2829507c3241Smlf 	uint_t		 resid_bytes;
2830507c3241Smlf 	uint_t		 resid_sectors;
2831507c3241Smlf 
2832507c3241Smlf 	lba_start = ata_pktp->ap_startsec;
2833507c3241Smlf 
2834507c3241Smlf 	if (ata_drvp->ad_flags & AD_EXT48)
2835507c3241Smlf 		lba_stop = ata_last_block_xferred_lba48(ata_ctlp);
2836507c3241Smlf 	else if (ata_drvp->ad_drive_bits & ATDH_LBA)
2837507c3241Smlf 		lba_stop = ata_last_block_xferred_lba28(ata_ctlp);
2838507c3241Smlf 	else /* CHS mode */
2839507c3241Smlf 		lba_stop = ata_last_block_xferred_chs(ata_drvp);
2840507c3241Smlf 
2841507c3241Smlf 	resid_sectors = lba_start + ata_pktp->ap_count - lba_stop;
2842507c3241Smlf 	resid_bytes = resid_sectors << SCTRSHFT;
2843507c3241Smlf 
2844507c3241Smlf 	ADBG_TRACE(("ata_disk_get_resid start 0x%x cnt 0x%x stop 0x%x\n",
2845*1bff1300SToomas Soome 	    lba_start, ata_pktp->ap_count, lba_stop));
2846507c3241Smlf 	ata_pktp->ap_resid = resid_bytes;
2847507c3241Smlf }
2848507c3241Smlf 
2849507c3241Smlf 
2850507c3241Smlf 
2851507c3241Smlf /*
2852507c3241Smlf  * Removable media commands *
2853507c3241Smlf  */
2854507c3241Smlf 
2855507c3241Smlf 
2856507c3241Smlf 
2857507c3241Smlf /*
2858507c3241Smlf  * get the media status
2859507c3241Smlf  *
2860507c3241Smlf  * NOTE: the error handling case probably isn't correct but it
2861507c3241Smlf  * will have to do until someone gives me a drive to test this on.
2862507c3241Smlf  */
2863507c3241Smlf static int
ata_disk_state(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2864*1bff1300SToomas Soome ata_disk_state(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
2865*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
2866507c3241Smlf {
2867507c3241Smlf 	int	*statep = (int *)ata_pktp->ap_v_addr;
2868507c3241Smlf 	uchar_t	 err;
2869507c3241Smlf 
2870507c3241Smlf 	ADBG_TRACE(("ata_disk_state\n"));
2871507c3241Smlf 	if (ata_command(ata_ctlp, ata_drvp, TRUE, TRUE, 5 * 1000000,
2872*1bff1300SToomas Soome 	    ATC_DOOR_LOCK, 0, 0, 0, 0, 0, 0)) {
2873507c3241Smlf 		*statep = DKIO_INSERTED;
2874507c3241Smlf 		return (ATA_FSM_RC_FINI);
2875507c3241Smlf 	}
2876507c3241Smlf 
2877507c3241Smlf 	err = ddi_get8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_error);
2878507c3241Smlf 	if (err & ATE_NM)
2879507c3241Smlf 		*statep = DKIO_EJECTED;
2880507c3241Smlf 	else
2881507c3241Smlf 		*statep = DKIO_NONE;
2882507c3241Smlf 
2883507c3241Smlf 	return (ATA_FSM_RC_FINI);
2884507c3241Smlf }
2885507c3241Smlf 
2886507c3241Smlf /*
2887507c3241Smlf  * eject the media
2888507c3241Smlf  */
2889507c3241Smlf 
2890507c3241Smlf static int
ata_disk_eject(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2891*1bff1300SToomas Soome ata_disk_eject(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
2892*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
2893507c3241Smlf {
2894507c3241Smlf 	ADBG_TRACE(("ata_disk_eject\n"));
2895507c3241Smlf 	if (ata_command(ata_ctlp, ata_drvp, TRUE, TRUE, 5 * 1000000,
2896*1bff1300SToomas Soome 	    ATC_EJECT, 0, 0, 0, 0, 0, 0)) {
2897507c3241Smlf 		return (ATA_FSM_RC_FINI);
2898507c3241Smlf 	}
2899507c3241Smlf 	ata_pktp->ap_flags |= AP_ERROR;
2900507c3241Smlf 	return (ATA_FSM_RC_FINI);
2901507c3241Smlf }
2902507c3241Smlf 
2903507c3241Smlf /*
2904507c3241Smlf  * lock the drive
2905507c3241Smlf  *
2906507c3241Smlf  */
2907507c3241Smlf static int
ata_disk_lock(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2908*1bff1300SToomas Soome ata_disk_lock(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
2909*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
2910507c3241Smlf {
2911507c3241Smlf 	ADBG_TRACE(("ata_disk_lock\n"));
2912507c3241Smlf 	if (ata_command(ata_ctlp, ata_drvp, TRUE, TRUE, 5 * 1000000,
2913*1bff1300SToomas Soome 	    ATC_DOOR_LOCK, 0, 0, 0, 0, 0, 0)) {
2914507c3241Smlf 		return (ATA_FSM_RC_FINI);
2915507c3241Smlf 	}
2916507c3241Smlf 	ata_pktp->ap_flags |= AP_ERROR;
2917507c3241Smlf 	return (ATA_FSM_RC_FINI);
2918507c3241Smlf }
2919507c3241Smlf 
2920507c3241Smlf 
2921507c3241Smlf /*
2922507c3241Smlf  * unlock the drive
2923507c3241Smlf  *
2924507c3241Smlf  */
2925507c3241Smlf static int
ata_disk_unlock(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2926*1bff1300SToomas Soome ata_disk_unlock(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
2927*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
2928507c3241Smlf {
2929507c3241Smlf 	ADBG_TRACE(("ata_disk_unlock\n"));
2930507c3241Smlf 	if (ata_command(ata_ctlp, ata_drvp, TRUE, TRUE, 5 * 1000000,
2931*1bff1300SToomas Soome 	    ATC_DOOR_UNLOCK, 0, 0, 0, 0, 0, 0)) {
2932507c3241Smlf 		return (ATA_FSM_RC_FINI);
2933507c3241Smlf 	}
2934507c3241Smlf 	ata_pktp->ap_flags |= AP_ERROR;
2935507c3241Smlf 	return (ATA_FSM_RC_FINI);
2936507c3241Smlf }
2937507c3241Smlf 
2938507c3241Smlf 
2939507c3241Smlf /*
2940507c3241Smlf  * put the drive into standby mode
2941507c3241Smlf  */
2942507c3241Smlf static int
ata_disk_standby(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2943*1bff1300SToomas Soome ata_disk_standby(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
2944*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
2945507c3241Smlf {
2946507c3241Smlf 	ADBG_TRACE(("ata_disk_standby\n"));
2947507c3241Smlf 	if (ata_command(ata_ctlp, ata_drvp, TRUE, TRUE, 5 * 1000000,
2948*1bff1300SToomas Soome 	    ATC_STANDBY_IM, 0, 0, 0, 0, 0, 0)) {
2949507c3241Smlf 		return (ATA_FSM_RC_FINI);
2950507c3241Smlf 	}
2951507c3241Smlf 	ata_pktp->ap_flags |= AP_ERROR;
2952507c3241Smlf 	return (ATA_FSM_RC_FINI);
2953507c3241Smlf }
2954507c3241Smlf 
2955507c3241Smlf 
2956507c3241Smlf /*
2957507c3241Smlf  * Recalibrate
2958507c3241Smlf  *
2959507c3241Smlf  * Note the extra long timeout value. This is necessary in case
2960507c3241Smlf  * the drive was in standby mode and needs to spin up the media.
2961507c3241Smlf  *
2962507c3241Smlf  */
2963507c3241Smlf static int
ata_disk_recalibrate(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2964*1bff1300SToomas Soome ata_disk_recalibrate(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
2965*1bff1300SToomas Soome     ata_pkt_t *ata_pktp)
2966507c3241Smlf {
2967507c3241Smlf 	ADBG_TRACE(("ata_disk_recalibrate\n"));
2968507c3241Smlf 	if (ata_command(ata_ctlp, ata_drvp, TRUE, TRUE, 31 * 1000000,
2969*1bff1300SToomas Soome 	    ATC_RECAL, 0, 0, 0, 0, 0, 0)) {
2970507c3241Smlf 		return (ATA_FSM_RC_FINI);
2971507c3241Smlf 	}
2972507c3241Smlf 	ata_pktp->ap_flags |= AP_ERROR;
2973507c3241Smlf 	return (ATA_FSM_RC_FINI);
2974507c3241Smlf }
2975507c3241Smlf 
2976507c3241Smlf /*
2977507c3241Smlf  * Copy a string of bytes that were obtained by Identify Device into a
2978507c3241Smlf  * string buffer provided by the caller.
2979507c3241Smlf  *
2980507c3241Smlf  * 1. Determine the amount to copy.  This is the lesser of the
2981507c3241Smlf  *    length of the source string or the space available in the user's
2982507c3241Smlf  *    buffer.
2983507c3241Smlf  * 2. The true length of the source string is always returned to the
2984507c3241Smlf  *    caller in the size field of the argument.
2985507c3241Smlf  * 3. Copy the string, add a terminating NUL character at the end.
2986507c3241Smlf  */
2987507c3241Smlf 
2988507c3241Smlf static int
ata_copy_dk_ioc_string(intptr_t arg,char * source,int length,int flag)2989507c3241Smlf ata_copy_dk_ioc_string(intptr_t arg, char *source, int length, int flag)
2990507c3241Smlf {
2991507c3241Smlf 	STRUCT_DECL(dadk_ioc_string, ds_arg);
2992507c3241Smlf 	int			destsize;
2993507c3241Smlf 	char			nulchar;
2994507c3241Smlf 	caddr_t			outp;
2995507c3241Smlf 
2996507c3241Smlf 	/*
2997507c3241Smlf 	 * The ioctls that use this routine are only available to
2998507c3241Smlf 	 * the kernel.
2999507c3241Smlf 	 */
3000507c3241Smlf 	if ((flag & FKIOCTL) == 0)
3001507c3241Smlf 		return (EFAULT);
3002507c3241Smlf 
3003507c3241Smlf 	STRUCT_INIT(ds_arg, flag & FMODELS);
3004507c3241Smlf 
3005507c3241Smlf 	/* 1. determine size of user's buffer */
3006507c3241Smlf 	if (ddi_copyin((caddr_t)arg, STRUCT_BUF(ds_arg), STRUCT_SIZE(ds_arg),
3007507c3241Smlf 	    flag))
3008507c3241Smlf 		return (EFAULT);
3009507c3241Smlf 	destsize = STRUCT_FGET(ds_arg, is_size);
3010507c3241Smlf 	if (destsize > length + 1)
3011507c3241Smlf 		destsize = length + 1;
3012507c3241Smlf 
3013507c3241Smlf 	/*
3014507c3241Smlf 	 * 2. Return the copied length to the caller.  Note: for
3015507c3241Smlf 	 * convenience, we actually copy the entire structure back out, not
3016507c3241Smlf 	 * just the length.  We don't change the is_buf field, so this
3017507c3241Smlf 	 * shouldn't break anything.
3018507c3241Smlf 	 */
3019507c3241Smlf 	STRUCT_FSET(ds_arg, is_size, length);
3020507c3241Smlf 	if (ddi_copyout(STRUCT_BUF(ds_arg), (caddr_t)arg, STRUCT_SIZE(ds_arg),
3021507c3241Smlf 	    flag))
3022507c3241Smlf 		return (EFAULT);
3023507c3241Smlf 
3024507c3241Smlf 	/* 3. copy the string and add a NULL terminator */
3025507c3241Smlf 	outp = STRUCT_FGETP(ds_arg, is_buf);
3026507c3241Smlf 	if (ddi_copyout(source, outp, destsize - 1, flag))
3027507c3241Smlf 		return (EFAULT);
3028507c3241Smlf 	nulchar = '\0';
3029507c3241Smlf 	if (ddi_copyout(&nulchar, outp + (destsize - 1), 1, flag))
3030507c3241Smlf 		return (EFAULT);
3031507c3241Smlf 	return (0);
3032507c3241Smlf }
3033507c3241Smlf 
3034507c3241Smlf /*
3035507c3241Smlf  * Sun branded drives are shipped write cache disabled.  The default is to
3036507c3241Smlf  * force write write caching on.
3037507c3241Smlf  */
3038507c3241Smlf static void
ata_set_write_cache(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp)3039507c3241Smlf ata_set_write_cache(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp)
3040507c3241Smlf {
3041507c3241Smlf 	char *path;
3042507c3241Smlf 
30433a7782feSxun ni - Sun Microsystems - Beijing China 	if (!(IS_WRITE_CACHE_SUPPORTED(ata_drvp->ad_id)))
30443a7782feSxun ni - Sun Microsystems - Beijing China 		return;
30453a7782feSxun ni - Sun Microsystems - Beijing China 
3046507c3241Smlf 	if (ata_write_cache == 1) {
3047507c3241Smlf 		if (ata_set_feature(ata_ctlp, ata_drvp, FC_WRITE_CACHE_ON, 0)
3048507c3241Smlf 		    == FALSE) {
3049507c3241Smlf 			path = kmem_alloc(MAXPATHLEN + 1, KM_NOSLEEP);
3050507c3241Smlf 			if (path != NULL) {
3051507c3241Smlf 				cmn_err(CE_WARN,
3052507c3241Smlf 				    "%s unable to enable write cache targ=%d",
3053507c3241Smlf 				    ddi_pathname(ata_ctlp->ac_dip, path),
3054507c3241Smlf 				    ata_drvp->ad_targ);
3055507c3241Smlf 				kmem_free(path, MAXPATHLEN + 1);
3056507c3241Smlf 			}
3057507c3241Smlf 		}
3058507c3241Smlf 	} else if (ata_write_cache == -1) {
3059507c3241Smlf 		if (ata_set_feature(ata_ctlp, ata_drvp, FC_WRITE_CACHE_OFF, 0)
3060507c3241Smlf 		    == FALSE) {
3061507c3241Smlf 			path = kmem_alloc(MAXPATHLEN + 1, KM_NOSLEEP);
3062507c3241Smlf 			if (path != NULL) {
3063507c3241Smlf 				cmn_err(CE_WARN,
3064507c3241Smlf 				    "%s unable to disable write cache targ=%d",
3065507c3241Smlf 				    ddi_pathname(ata_ctlp->ac_dip, path),
3066507c3241Smlf 				    ata_drvp->ad_targ);
3067507c3241Smlf 				kmem_free(path, MAXPATHLEN + 1);
3068507c3241Smlf 			}
3069507c3241Smlf 		}
3070507c3241Smlf 	}
3071507c3241Smlf }
30720f2c99a4Syt 
30730f2c99a4Syt /*
30740f2c99a4Syt  * Call set feature to spin-up the device.
30750f2c99a4Syt  */
30760f2c99a4Syt static int
ata_disk_set_feature_spinup(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)30770f2c99a4Syt ata_disk_set_feature_spinup(
30780f2c99a4Syt 	ata_ctl_t	*ata_ctlp,
30790f2c99a4Syt 	ata_drv_t	*ata_drvp,
30800f2c99a4Syt 	ata_pkt_t	*ata_pktp)
30810f2c99a4Syt {
30820f2c99a4Syt 	int rc;
30830f2c99a4Syt 
30840f2c99a4Syt 	ADBG_TRACE(("ata_disk_set_feature_spinup entered\n"));
30850f2c99a4Syt 
30860f2c99a4Syt 	rc = ata_set_feature(ata_ctlp, ata_drvp, 0x07, 0);
30870f2c99a4Syt 	if (!rc)
30880f2c99a4Syt 		ata_pktp->ap_flags |= AP_ERROR;
30890f2c99a4Syt 
30900f2c99a4Syt 	return (ATA_FSM_RC_FINI);
30910f2c99a4Syt }
30920f2c99a4Syt 
30930f2c99a4Syt /*
30940f2c99a4Syt  * Update device ata_id content - IDENTIFY DEVICE command.
30950f2c99a4Syt  */
30960f2c99a4Syt static int
ata_disk_id_update(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)30970f2c99a4Syt ata_disk_id_update(
30980f2c99a4Syt 	ata_ctl_t	*ata_ctlp,
30990f2c99a4Syt 	ata_drv_t	*ata_drvp,
31000f2c99a4Syt 	ata_pkt_t	*ata_pktp)
31010f2c99a4Syt {
31020f2c99a4Syt 	ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
31030f2c99a4Syt 	caddr_t		 ioaddr1 = ata_ctlp->ac_ioaddr1;
31040f2c99a4Syt 	ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
31050f2c99a4Syt 	caddr_t		 ioaddr2 = ata_ctlp->ac_ioaddr2;
31060f2c99a4Syt 	struct ata_id *aidp = &ata_drvp->ad_id;
31070f2c99a4Syt 	int rc;
31080f2c99a4Syt 
31090f2c99a4Syt 	ADBG_TRACE(("ata_disk_id_update entered\n"));
31100f2c99a4Syt 
31110f2c99a4Syt 	/*
31120f2c99a4Syt 	 * select the appropriate drive and LUN
31130f2c99a4Syt 	 */
31140f2c99a4Syt 	ddi_put8(io_hdl1, (uchar_t *)ioaddr1 + AT_DRVHD,
31150f2c99a4Syt 	    ata_drvp->ad_drive_bits);
31169f49ae27Smlf 	ata_nsecwait(400);
31170f2c99a4Syt 
31180f2c99a4Syt 	/*
31190f2c99a4Syt 	 * make certain the drive is selected, and wait for not busy
31200f2c99a4Syt 	 */
31210f2c99a4Syt 	if (!ata_wait(io_hdl2, ioaddr2, ATS_DRDY, ATS_BSY, 5 * 1000000)) {
31220f2c99a4Syt 		ADBG_ERROR(("ata_disk_id_update: select failed\n"));
31230f2c99a4Syt 		ata_pktp->ap_flags |= AP_ERROR;
31240f2c99a4Syt 		return (ATA_FSM_RC_FINI);
31250f2c99a4Syt 	}
31260f2c99a4Syt 
31270f2c99a4Syt 	rc = ata_disk_id(io_hdl1, ioaddr1, io_hdl2, ioaddr2, aidp);
31280f2c99a4Syt 
31290f2c99a4Syt 	if (!rc) {
31300f2c99a4Syt 		ata_pktp->ap_flags |= AP_ERROR;
31310f2c99a4Syt 	} else {
31320f2c99a4Syt 		swab(aidp->ai_drvser, aidp->ai_drvser,
31330f2c99a4Syt 		    sizeof (aidp->ai_drvser));
31340f2c99a4Syt 		swab(aidp->ai_fw, aidp->ai_fw,
31350f2c99a4Syt 		    sizeof (aidp->ai_fw));
31360f2c99a4Syt 		swab(aidp->ai_model, aidp->ai_model,
31370f2c99a4Syt 		    sizeof (aidp->ai_model));
31380f2c99a4Syt 	}
31390f2c99a4Syt 
31400f2c99a4Syt 	return (ATA_FSM_RC_FINI);
31410f2c99a4Syt }
31420f2c99a4Syt 
31430f2c99a4Syt /*
31440f2c99a4Syt  * Update device firmware.
31450f2c99a4Syt  */
31460f2c99a4Syt static int
ata_disk_update_fw(gtgt_t * gtgtp,ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,caddr_t fwfile,uint_t size,uint8_t type,int flag)31470f2c99a4Syt ata_disk_update_fw(gtgt_t *gtgtp, ata_ctl_t *ata_ctlp,
3148*1bff1300SToomas Soome     ata_drv_t *ata_drvp, caddr_t fwfile,
3149*1bff1300SToomas Soome     uint_t size, uint8_t type, int flag)
31500f2c99a4Syt {
31510f2c99a4Syt 	ata_pkt_t	*ata_pktp;
31520f2c99a4Syt 	gcmd_t		*gcmdp = NULL;
31530f2c99a4Syt 	caddr_t		fwfile_memp = NULL, tmp_fwfile_memp;
31540f2c99a4Syt 	uint_t		total_sec_count, sec_count, start_sec = 0;
31550f2c99a4Syt 	uint8_t		cmd_type;
31560f2c99a4Syt 	int		rc;
31570f2c99a4Syt 
31580f2c99a4Syt 	/*
31590f2c99a4Syt 	 * First check whether DOWNLOAD MICROCODE command is supported
31600f2c99a4Syt 	 */
31610f2c99a4Syt 	if (!(ata_drvp->ad_id.ai_cmdset83 & 0x1)) {
31620f2c99a4Syt 		ADBG_ERROR(("drive doesn't support download "
31630f2c99a4Syt 		    "microcode command\n"));
31640f2c99a4Syt 		return (ENOTSUP);
31650f2c99a4Syt 	}
31660f2c99a4Syt 
31670f2c99a4Syt 	switch (type) {
31680f2c99a4Syt 	case FW_TYPE_TEMP:
31690f2c99a4Syt 		cmd_type = ATCM_FW_TEMP;
31700f2c99a4Syt 		break;
31710f2c99a4Syt 
31720f2c99a4Syt 	case FW_TYPE_PERM:
31730f2c99a4Syt 		cmd_type = ATCM_FW_PERM;
31740f2c99a4Syt 		break;
31750f2c99a4Syt 
31760f2c99a4Syt 	default:
31770f2c99a4Syt 		return (EINVAL);
31780f2c99a4Syt 	}
31790f2c99a4Syt 
31800f2c99a4Syt 	/* Temporary subcommand is obsolete in ATA/ATAPI-8 version */
31810f2c99a4Syt 	if (cmd_type == ATCM_FW_TEMP) {
31820f2c99a4Syt 		if (ata_drvp->ad_id.ai_majorversion & ATAC_MAJVER_8) {
31830f2c99a4Syt 			ADBG_ERROR(("Temporary use is obsolete in "
31840f2c99a4Syt 			    "ATA/ATAPI-8 version\n"));
31850f2c99a4Syt 			return (ENOTSUP);
31860f2c99a4Syt 		}
31870f2c99a4Syt 	}
31880f2c99a4Syt 
31890f2c99a4Syt 	total_sec_count = size >> SCTRSHFT;
31900f2c99a4Syt 	if (total_sec_count > MAX_FWFILE_SIZE_ONECMD) {
31910f2c99a4Syt 		if (cmd_type == ATCM_FW_TEMP) {
31920f2c99a4Syt 			ADBG_ERROR(("firmware size: %x sectors is too large\n",
31930f2c99a4Syt 			    total_sec_count));
31940f2c99a4Syt 			return (EINVAL);
31950f2c99a4Syt 		} else {
31960f2c99a4Syt 			ADBG_WARN(("firmware size: %x sectors is larger than"
31970f2c99a4Syt 			    " one command, need to use the multicommand"
31980f2c99a4Syt 			    " subcommand\n", total_sec_count));
31990f2c99a4Syt 
32000f2c99a4Syt 			cmd_type = ATCM_FW_MULTICMD;
32010f2c99a4Syt 			if (!(ata_drvp->ad_id.ai_padding2[15] & 0x10)) {
32020f2c99a4Syt 				ADBG_ERROR(("This drive doesn't support "
32030f2c99a4Syt 				    "the multicommand subcommand\n"));
32040f2c99a4Syt 				return (ENOTSUP);
32050f2c99a4Syt 			}
32060f2c99a4Syt 		}
32070f2c99a4Syt 	}
32080f2c99a4Syt 
32090f2c99a4Syt 	fwfile_memp = kmem_zalloc(size, KM_SLEEP);
32100f2c99a4Syt 
32110f2c99a4Syt 	if (ddi_copyin(fwfile, fwfile_memp, size, flag)) {
32120f2c99a4Syt 		ADBG_ERROR(("ata_disk_update_fw copyin failed\n"));
32130f2c99a4Syt 		rc = EFAULT;
32140f2c99a4Syt 		goto done;
32150f2c99a4Syt 	}
32160f2c99a4Syt 
32170f2c99a4Syt 	tmp_fwfile_memp = fwfile_memp;
32180f2c99a4Syt 
32190f2c99a4Syt 	for (; total_sec_count > 0; ) {
32200f2c99a4Syt 		if ((gcmdp == NULL) && !(gcmdp =
32210f2c99a4Syt 		    ghd_gcmd_alloc(gtgtp, sizeof (*ata_pktp), TRUE))) {
32220f2c99a4Syt 			ADBG_ERROR(("ata_disk_update_fw alloc failed\n"));
32230f2c99a4Syt 			rc = ENOMEM;
32240f2c99a4Syt 			goto done;
32250f2c99a4Syt 		}
32260f2c99a4Syt 
32270f2c99a4Syt 		/* set the back ptr from the ata_pkt to the gcmd_t */
32280f2c99a4Syt 		ata_pktp = GCMD2APKT(gcmdp);
32290f2c99a4Syt 		ata_pktp->ap_gcmdp = gcmdp;
32300f2c99a4Syt 		ata_pktp->ap_hd = ata_drvp->ad_drive_bits;
32310f2c99a4Syt 		ata_pktp->ap_bytes_per_block = ata_drvp->ad_bytes_per_block;
32320f2c99a4Syt 
32330f2c99a4Syt 		/* use PIO mode to update disk firmware */
32340f2c99a4Syt 		ata_pktp->ap_start = ata_disk_start_pio_out;
32350f2c99a4Syt 		ata_pktp->ap_intr = ata_disk_intr_pio_out;
32360f2c99a4Syt 		ata_pktp->ap_complete = NULL;
32370f2c99a4Syt 
32380f2c99a4Syt 		ata_pktp->ap_cmd = ATC_LOAD_FW;
32390f2c99a4Syt 		/* use ap_bcount to set subcommand code */
32400f2c99a4Syt 		ata_pktp->ap_bcount = (size_t)cmd_type;
32410f2c99a4Syt 		ata_pktp->ap_pciide_dma = FALSE;
32420f2c99a4Syt 		ata_pktp->ap_sg_cnt = 0;
32430f2c99a4Syt 
32440f2c99a4Syt 		sec_count = min(total_sec_count, MAX_FWFILE_SIZE_ONECMD);
32450f2c99a4Syt 		ata_pktp->ap_flags = 0;
32460f2c99a4Syt 
3247f304523cSzhongyan gu - Sun Microsystems - Beijing China 		ata_pktp->ap_count = (ushort_t)sec_count;
32480f2c99a4Syt 		ata_pktp->ap_startsec = start_sec;
32490f2c99a4Syt 		ata_pktp->ap_v_addr = tmp_fwfile_memp;
32500f2c99a4Syt 		ata_pktp->ap_resid = sec_count << SCTRSHFT;
32510f2c99a4Syt 
32520f2c99a4Syt 		/* add it to the queue, and use POLL mode */
32530f2c99a4Syt 		rc = ghd_transport(&ata_ctlp->ac_ccc, gcmdp, gcmdp->cmd_gtgtp,
32540f2c99a4Syt 		    ata_disk_updatefw_time, TRUE, NULL);
32550f2c99a4Syt 
32560f2c99a4Syt 		if (rc != TRAN_ACCEPT) {
32570f2c99a4Syt 			/* this should never, ever happen */
32580f2c99a4Syt 			rc = ENOTSUP;
32590f2c99a4Syt 			goto done;
32600f2c99a4Syt 		}
32610f2c99a4Syt 
32620f2c99a4Syt 		if (ata_pktp->ap_flags & AP_ERROR) {
32630f2c99a4Syt 			if (ata_pktp->ap_error & ATE_ABORT) {
32640f2c99a4Syt 				rc = ENOTSUP;
32650f2c99a4Syt 			} else
32660f2c99a4Syt 				rc = EIO;
32670f2c99a4Syt 			goto done;
32680f2c99a4Syt 
32690f2c99a4Syt 		} else {
32700f2c99a4Syt 			total_sec_count -= sec_count;
32710f2c99a4Syt 			tmp_fwfile_memp += sec_count << SCTRSHFT;
32720f2c99a4Syt 			start_sec += sec_count;
32730f2c99a4Syt 		}
32740f2c99a4Syt 	}
32750f2c99a4Syt 
32760f2c99a4Syt 	rc = 0;
32770f2c99a4Syt done:
32780f2c99a4Syt 	if (gcmdp != NULL)
32790f2c99a4Syt 		ghd_gcmd_free(gcmdp);
32800f2c99a4Syt 
32810f2c99a4Syt 	kmem_free(fwfile_memp, size);
32820f2c99a4Syt 
32830f2c99a4Syt 	return (rc);
32840f2c99a4Syt }
3285