1507c3241Smlf /*
2507c3241Smlf * CDDL HEADER START
3507c3241Smlf *
4507c3241Smlf * The contents of this file are subject to the terms of the
5507c3241Smlf * 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);
1180f2c99a4Syt160523 static int ata_disk_update_fw(gtgt_t *gtgtp, ata_ctl_t *ata_ctlp,
1190f2c99a4Syt160523 ata_drv_t *ata_drvp, caddr_t fwfile, uint_t size,
1200f2c99a4Syt160523 uint8_t type, int flag);
1210f2c99a4Syt160523 static int ata_disk_set_feature_spinup(ata_ctl_t *ata_ctlp,
1220f2c99a4Syt160523 ata_drv_t *ata_drvp, ata_pkt_t *ata_pktp);
1230f2c99a4Syt160523 static int ata_disk_id_update(ata_ctl_t *ata_ctlp,
1240f2c99a4Syt160523 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
1350f2c99a4Syt160523 /* timeout value for device update firmware */
1360f2c99a4Syt160523 int ata_disk_updatefw_time = 60;
1370f2c99a4Syt160523
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;
270507c3241Smlf int len;
271507c3241Smlf int val;
272507c3241Smlf int mode;
273507c3241Smlf short *chs;
274507c3241Smlf 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,
308507c3241Smlf ata_drvp->ad_targ+1);
309507c3241Smlf if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_root_node(), 0,
310507c3241Smlf 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 "
329507c3241Smlf "different from physical, and no LBA support.",
330507c3241Smlf (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 /
354507c3241Smlf (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,
413507c3241Smlf 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",
497507c3241Smlf (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",
554507c3241Smlf 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 *
613507c3241Smlf 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",
679507c3241Smlf 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,
738507c3241Smlf 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) {
758507c3241Smlf if (ata_drvp->ad_flags & AD_MUTEX_INIT)
759507c3241Smlf 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,
788507c3241Smlf "target", 0);
789507c3241Smlf cmn_err(CE_CONT, "?%s%d at %s%d target %d lun %d\n",
790507c3241Smlf ddi_driver_name(r), ddi_get_instance(r),
791507c3241Smlf 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,
836507c3241Smlf 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 =
844507c3241Smlf 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,
852507c3241Smlf 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;
862507c3241Smlf 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, >GTP2ATAP(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,
931507c3241Smlf NULL);
932*1bff1300SToomas Soome break;
933*1bff1300SToomas Soome case RESET_ALL:
934507c3241Smlf rc = ghd_tran_reset_bus(&ata_drvp->ad_ctlp->ac_ccc, gtgtp,
935507c3241Smlf 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);
9590f2c99a4Syt160523 int rc, rc2;
9604d27faddSmarx struct tgdk_geom tgdk;
9614d27faddSmarx int wce;
962507c3241Smlf struct ata_id *aidp = &ata_drvp->ad_id;
9630f2c99a4Syt160523 dk_updatefw_t updatefw;
9640f2c99a4Syt160523 #ifdef _MULTI_DATAMODEL
9650f2c99a4Syt160523 dk_updatefw_32_t updatefw32;
9660f2c99a4Syt160523 #endif
9670f2c99a4Syt160523 dk_disk_id_t dk_disk_id;
9680f2c99a4Syt160523 char buf[80];
9690f2c99a4Syt160523 int i;
9700f2c99a4Syt160523
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,
1000507c3241Smlf sizeof (aidp->ai_model), flag);
1001507c3241Smlf return (rc);
1002507c3241Smlf
10030f2c99a4Syt160523 /* 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) ||
1022507c3241Smlf ((aidp->ai_majorversion & ATAC_MAJVER_4) == 0) ||
1023507c3241Smlf (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,
1032507c3241Smlf gtgtp);
1033507c3241Smlf break;
1034507c3241Smlf
1035507c3241Smlf case DCMD_LOCK:
1036507c3241Smlf case DKIOCLOCK:
1037507c3241Smlf rc = ata_queue_cmd(ata_disk_lock, NULL, ata_ctlp, ata_drvp,
1038507c3241Smlf gtgtp);
1039507c3241Smlf break;
1040507c3241Smlf
1041507c3241Smlf case DCMD_UNLOCK:
1042507c3241Smlf case DKIOCUNLOCK:
1043507c3241Smlf rc = ata_queue_cmd(ata_disk_unlock, NULL, ata_ctlp, ata_drvp,
1044507c3241Smlf gtgtp);
1045507c3241Smlf break;
1046507c3241Smlf
1047507c3241Smlf case DCMD_START_MOTOR:
1048507c3241Smlf case CDROMSTART:
1049507c3241Smlf rc = ata_queue_cmd(ata_disk_recalibrate, NULL, ata_ctlp,
1050507c3241Smlf 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,
1056507c3241Smlf gtgtp);
1057507c3241Smlf break;
1058507c3241Smlf
1059507c3241Smlf case DKIOCEJECT:
1060507c3241Smlf case CDROMEJECT:
1061507c3241Smlf rc = ata_queue_cmd(ata_disk_eject, NULL, ata_ctlp, ata_drvp,
1062507c3241Smlf gtgtp);
1063507c3241Smlf break;
1064507c3241Smlf
10650f2c99a4Syt160523 case DKIOC_UPDATEFW:
10660f2c99a4Syt160523
10670f2c99a4Syt160523 /*
10680f2c99a4Syt160523 * Call DOWNLOAD MICROCODE command to update device
10690f2c99a4Syt160523 * firmware.
10700f2c99a4Syt160523 *
10710f2c99a4Syt160523 * return value:
10720f2c99a4Syt160523 * normal 0 Download microcode success
10730f2c99a4Syt160523 * error EFAULT Bad address
10740f2c99a4Syt160523 * ENXIO No such device or address
10750f2c99a4Syt160523 * EINVAL Invalid argument
10760f2c99a4Syt160523 * ENOMEM Not enough core
10770f2c99a4Syt160523 * ENOTSUP Operation not supported
10780f2c99a4Syt160523 * EIO I/O error
10790f2c99a4Syt160523 * EPERM Not owner
10800f2c99a4Syt160523 */
10810f2c99a4Syt160523
10820f2c99a4Syt160523 /*
10830f2c99a4Syt160523 * The following code deals with handling 32-bit request
10840f2c99a4Syt160523 * in 64-bit kernel.
10850f2c99a4Syt160523 */
10860f2c99a4Syt160523 #ifdef _MULTI_DATAMODEL
10870f2c99a4Syt160523 if (ddi_model_convert_from(flag & FMODELS) ==
10880f2c99a4Syt160523 DDI_MODEL_ILP32) {
10890f2c99a4Syt160523 if (ddi_copyin((void *)arg, &updatefw32,
10900f2c99a4Syt160523 sizeof (dk_updatefw_32_t), flag))
10910f2c99a4Syt160523 return (EFAULT);
10920f2c99a4Syt160523
10930f2c99a4Syt160523 updatefw.dku_ptrbuf =
10940f2c99a4Syt160523 (caddr_t)(uintptr_t)updatefw32.dku_ptrbuf;
10950f2c99a4Syt160523 updatefw.dku_size = updatefw32.dku_size;
10960f2c99a4Syt160523 updatefw.dku_type = updatefw32.dku_type;
10970f2c99a4Syt160523 } else {
10980f2c99a4Syt160523 if (ddi_copyin((void *)arg, &updatefw,
10990f2c99a4Syt160523 sizeof (dk_updatefw_t), flag))
11000f2c99a4Syt160523 return (EFAULT);
11010f2c99a4Syt160523 }
11020f2c99a4Syt160523 #else
11030f2c99a4Syt160523 if (ddi_copyin((void *)arg, &updatefw,
11040f2c99a4Syt160523 sizeof (dk_updatefw_t), flag))
11050f2c99a4Syt160523 return (EFAULT);
11060f2c99a4Syt160523 #endif
11070f2c99a4Syt160523 rc = ata_disk_update_fw(gtgtp, ata_ctlp, ata_drvp,
11080f2c99a4Syt160523 updatefw.dku_ptrbuf, updatefw.dku_size,
11090f2c99a4Syt160523 updatefw.dku_type, flag);
11100f2c99a4Syt160523
11110f2c99a4Syt160523 /*
11120f2c99a4Syt160523 * According to ATA8-ACS spec, the new microcode should
11130f2c99a4Syt160523 * become effective immediately after the transfer of the
11140f2c99a4Syt160523 * last data segment has completed, so here we will call
11150f2c99a4Syt160523 * IDENTIFY DEVICE command immediately to update
11160f2c99a4Syt160523 * ata_id content when success.
11170f2c99a4Syt160523 */
11180f2c99a4Syt160523 if (rc == 0) {
11190f2c99a4Syt160523 rc2 = ata_queue_cmd(ata_disk_id_update, NULL,
11200f2c99a4Syt160523 ata_ctlp, ata_drvp, gtgtp);
11210f2c99a4Syt160523 if (rc2 != TRUE) {
11220f2c99a4Syt160523 return (ENXIO);
11230f2c99a4Syt160523 } else {
11240f2c99a4Syt160523 /*
11250f2c99a4Syt160523 * Check whether the content of the IDENTIFY
11260f2c99a4Syt160523 * DEVICE data is incomplete, if yes, it's
11270f2c99a4Syt160523 * because the device supports the Power-up
11280f2c99a4Syt160523 * in Standby feature set, and we will first
11290f2c99a4Syt160523 * check word 2, and then decide whether need
11300f2c99a4Syt160523 * to call set feature to spin-up the device,
11310f2c99a4Syt160523 * and then call IDENTIFY DEVICE command again.
11320f2c99a4Syt160523 */
11330f2c99a4Syt160523 aidp = &ata_drvp->ad_id;
11340f2c99a4Syt160523 if (aidp->ai_config & ATA_ID_INCMPT) {
11350f2c99a4Syt160523 if (aidp->ai_resv0 == 0x37c8 ||
11360f2c99a4Syt160523 aidp->ai_resv0 == 0x738c) {
11370f2c99a4Syt160523 /* Spin-up the device */
11380f2c99a4Syt160523 (void) ata_queue_cmd(
11390f2c99a4Syt160523 ata_disk_set_feature_spinup,
11400f2c99a4Syt160523 NULL,
11410f2c99a4Syt160523 ata_ctlp,
11420f2c99a4Syt160523 ata_drvp,
11430f2c99a4Syt160523 gtgtp);
11440f2c99a4Syt160523 }
11450f2c99a4Syt160523
11460f2c99a4Syt160523 /* Try to update ata_id again */
11470f2c99a4Syt160523 rc2 = ata_queue_cmd(
11480f2c99a4Syt160523 ata_disk_id_update,
11490f2c99a4Syt160523 NULL,
11500f2c99a4Syt160523 ata_ctlp,
11510f2c99a4Syt160523 ata_drvp,
11520f2c99a4Syt160523 gtgtp);
11530f2c99a4Syt160523 if (rc2 != TRUE) {
11540f2c99a4Syt160523 return (ENXIO);
11550f2c99a4Syt160523 } else {
11560f2c99a4Syt160523 aidp = &ata_drvp->ad_id;
11570f2c99a4Syt160523 if (aidp->ai_config &
11580f2c99a4Syt160523 ATA_ID_INCMPT)
11590f2c99a4Syt160523 return (ENXIO);
11600f2c99a4Syt160523 }
11610f2c99a4Syt160523 }
11620f2c99a4Syt160523
11630f2c99a4Syt160523 /*
11640f2c99a4Syt160523 * Dump the drive information.
11650f2c99a4Syt160523 */
11660f2c99a4Syt160523 ATAPRT(("?\tUpdate firmware of %s device at "
11670f2c99a4Syt160523 "targ %d, lun %d lastlun 0x%x\n",
11680f2c99a4Syt160523 (ATAPIDRV(ata_drvp) ? "ATAPI":"IDE"),
11690f2c99a4Syt160523 ata_drvp->ad_targ, ata_drvp->ad_lun,
11700f2c99a4Syt160523 aidp->ai_lastlun));
11710f2c99a4Syt160523
11720f2c99a4Syt160523 (void) strncpy(buf, aidp->ai_model,
11730f2c99a4Syt160523 sizeof (aidp->ai_model));
11740f2c99a4Syt160523 buf[sizeof (aidp->ai_model)] = '\0';
11750f2c99a4Syt160523 for (i = sizeof (aidp->ai_model) - 1;
11760f2c99a4Syt160523 buf[i] == ' '; i--)
11770f2c99a4Syt160523 buf[i] = '\0';
11780f2c99a4Syt160523 ATAPRT(("?\tmodel %s\n", buf));
11790f2c99a4Syt160523
11800f2c99a4Syt160523 (void) strncpy(buf, aidp->ai_fw,
11810f2c99a4Syt160523 sizeof (aidp->ai_fw));
11820f2c99a4Syt160523 buf[sizeof (aidp->ai_fw)] = '\0';
11830f2c99a4Syt160523 for (i = sizeof (aidp->ai_fw) - 1;
11840f2c99a4Syt160523 buf[i] == ' '; i--)
11850f2c99a4Syt160523 buf[i] = '\0';
11860f2c99a4Syt160523 ATAPRT(("?\tfw %s\n", buf));
11870f2c99a4Syt160523 }
11880f2c99a4Syt160523 }
11890f2c99a4Syt160523 return (rc);
11900f2c99a4Syt160523
11910f2c99a4Syt160523 case DKIOC_GETDISKID:
11920f2c99a4Syt160523 bzero(&dk_disk_id, sizeof (dk_disk_id_t));
11930f2c99a4Syt160523
11940f2c99a4Syt160523 dk_disk_id.dkd_dtype = DKD_ATA_TYPE;
11950f2c99a4Syt160523
11960f2c99a4Syt160523 /* Get the model number */
11970f2c99a4Syt160523 (void) strncpy(dk_disk_id.disk_id.ata_disk_id.dkd_amodel,
11980f2c99a4Syt160523 aidp->ai_model, sizeof (aidp->ai_model));
11990f2c99a4Syt160523
12000f2c99a4Syt160523 /* Get the firmware revision */
12010f2c99a4Syt160523 (void) strncpy(dk_disk_id.disk_id.ata_disk_id.dkd_afwver,
12020f2c99a4Syt160523 aidp->ai_fw, sizeof (aidp->ai_fw));
12030f2c99a4Syt160523
12040f2c99a4Syt160523 /* Get the serial number */
12050f2c99a4Syt160523 (void) strncpy(dk_disk_id.disk_id.ata_disk_id.dkd_aserial,
12060f2c99a4Syt160523 aidp->ai_drvser, sizeof (aidp->ai_drvser));
12070f2c99a4Syt160523
12080f2c99a4Syt160523 if (ddi_copyout(&dk_disk_id, (void *)arg,
12090f2c99a4Syt160523 sizeof (dk_disk_id_t), flag))
12100f2c99a4Syt160523 return (EFAULT);
12110f2c99a4Syt160523 else
12120f2c99a4Syt160523 return (0);
12130f2c99a4Syt160523
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,
1250507c3241Smlf 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,
1288507c3241Smlf (sizeof (cmpkt_t) + sizeof (ata_pkt_t)),
1289507c3241Smlf (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(>GTP2ATAP(gtgtp)->ac_ccc, gcmdp, bp, flags,
1415507c3241Smlf callback, arg, >GTP2ATATGTP(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),
1537507c3241Smlf 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(>GTP2ATAP(gtgtp)->ac_ccc, gcmdp,
1564507c3241Smlf byte_count, ATA_DMA_NSEGS, &byte_count) == FALSE) ||
1565507c3241Smlf (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",
1669507c3241Smlf 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),
1731507c3241Smlf 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;
1849507c3241Smlf /* automatically truncate to char */
1850507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_sect,
1851507c3241Smlf (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));
1854507c3241Smlf /* 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,
1869507c3241Smlf 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",
1877507c3241Smlf ata_pktp, ata_pktp->ap_flags));
1878507c3241Smlf ADBG_TRANSPORT(("\tcommand=0x%x, sect=0x%lx\n",
1879507c3241Smlf ata_pktp->ap_cmd, ata_pktp->ap_startsec));
1880507c3241Smlf ADBG_TRANSPORT(("\tcount=0x%x, drvhd = 0x%x\n",
1881507c3241Smlf 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,
1897507c3241Smlf 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,
1910507c3241Smlf ATS_DRDY, ATS_BSY, 5 * 1000000)) {
1911507c3241Smlf ADBG_ERROR(("ata_disk_start: select failed\n"));
1912507c3241Smlf return (FALSE);
1913507c3241Smlf }
1914507c3241Smlf
19150f2c99a4Syt160523 if (ata_pktp->ap_cmd == ATC_LOAD_FW) {
19160f2c99a4Syt160523
19170f2c99a4Syt160523 /* the sector count is 16 bits wide */
19180f2c99a4Syt160523 ddi_put8(io_hdl1, ata_ctlp->ac_count, ata_pktp->ap_count);
19190f2c99a4Syt160523 ddi_put8(io_hdl1, ata_ctlp->ac_sect, ata_pktp->ap_count >> 8);
19200f2c99a4Syt160523 ddi_put8(io_hdl1, ata_ctlp->ac_lcyl, ata_pktp->ap_startsec);
19210f2c99a4Syt160523 ddi_put8(io_hdl1, ata_ctlp->ac_hcyl,
19220f2c99a4Syt160523 ata_pktp->ap_startsec >> 8);
19230f2c99a4Syt160523
19240f2c99a4Syt160523 /* put subcommand for DOWNLOAD MICROCODE */
19250f2c99a4Syt160523 ddi_put8(io_hdl1, ata_ctlp->ac_feature, ata_pktp->ap_bcount);
19260f2c99a4Syt160523 } else {
19270f2c99a4Syt160523
1928507c3241Smlf /*
1929507c3241Smlf * We use different methods for loading the task file
1930507c3241Smlf * registers, depending on whether the disk
1931507c3241Smlf * uses LBA or CHS addressing and whether 48-bit
1932507c3241Smlf * extended addressing is to be used.
1933507c3241Smlf */
1934507c3241Smlf if (!(ata_drvp->ad_drive_bits & ATDH_LBA))
1935507c3241Smlf ata_disk_load_regs_chs(ata_pktp, ata_drvp);
1936507c3241Smlf else if (ata_drvp->ad_flags & AD_EXT48)
1937507c3241Smlf ata_disk_load_regs_lba48(ata_pktp, ata_drvp);
1938507c3241Smlf else
1939507c3241Smlf ata_disk_load_regs_lba28(ata_pktp, ata_drvp);
1940507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_feature, 0);
19410f2c99a4Syt160523 }
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,
1963507c3241Smlf 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,
1988507c3241Smlf 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,
2003507c3241Smlf 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,
2027507c3241Smlf 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,
2042507c3241Smlf 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,
2107507c3241Smlf 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,
2137507c3241Smlf ATS_DRQ, ATS_BSY, /* okay */
2138507c3241Smlf ATS_ERR, ATS_BSY, /* cmd failed */
2139507c3241Smlf ATS_DF, ATS_BSY, /* drive failed */
2140507c3241Smlf 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,
2230507c3241Smlf 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,
2247507c3241Smlf 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,
2253507c3241Smlf ata_ctlp->ac_altstatus);
2254507c3241Smlf ata_pktp->ap_error = ddi_get8(ata_ctlp->ac_iohandle1,
2255507c3241Smlf 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,
2272507c3241Smlf 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",
2302507c3241Smlf 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,
2320507c3241Smlf 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,
2357507c3241Smlf 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",
2381507c3241Smlf 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,
2415507c3241Smlf 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",
2433507c3241Smlf 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,
2480507c3241Smlf 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",
2499507c3241Smlf 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",
2538507c3241Smlf 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,
2547507c3241Smlf 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",
2576507c3241Smlf 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,
2585507c3241Smlf 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,
2616507c3241Smlf ata_disk_init_dev_parm_wait,
2617507c3241Smlf ATC_SETPARAM,
2618507c3241Smlf 0, /* feature n/a */
2619507c3241Smlf ata_drvp->ad_phsec, /* max sector (1-based) */
2620507c3241Smlf 0, /* sector n/a */
2621507c3241Smlf (ata_drvp->ad_phhd -1), /* max head (0-based) */
2622507c3241Smlf 0, /* cyl_low n/a */
2623507c3241Smlf 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,
2656507c3241Smlf sizeof (inqp->inq_pid));
2657507c3241Smlf (void) strncpy(inqp->inq_revision, ata_idp->ai_fw,
2658507c3241Smlf 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,
2676507c3241Smlf ata_disk_set_mult_wait,
2677507c3241Smlf ATC_SETMULT,
2678507c3241Smlf 0, /* feature n/a */
2679507c3241Smlf ata_drvp->ad_block_factor, /* count */
2680507c3241Smlf 0, /* sector n/a */
2681507c3241Smlf 0, /* head n/a */
2682507c3241Smlf 0, /* cyl_low n/a */
2683507c3241Smlf 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,
2709507c3241Smlf 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,
2825507c3241Smlf 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",
2845507c3241Smlf 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,
2865507c3241Smlf 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,
2872507c3241Smlf 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,
2892507c3241Smlf 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,
2896507c3241Smlf 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,
2909507c3241Smlf 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,
2913507c3241Smlf 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,
2927507c3241Smlf 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,
2931507c3241Smlf 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,
2944507c3241Smlf 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,
2948507c3241Smlf 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,
2965507c3241Smlf 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,
2969507c3241Smlf 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 }
30720f2c99a4Syt160523
30730f2c99a4Syt160523 /*
30740f2c99a4Syt160523 * Call set feature to spin-up the device.
30750f2c99a4Syt160523 */
30760f2c99a4Syt160523 static int
ata_disk_set_feature_spinup(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)30770f2c99a4Syt160523 ata_disk_set_feature_spinup(
30780f2c99a4Syt160523 ata_ctl_t *ata_ctlp,
30790f2c99a4Syt160523 ata_drv_t *ata_drvp,
30800f2c99a4Syt160523 ata_pkt_t *ata_pktp)
30810f2c99a4Syt160523 {
30820f2c99a4Syt160523 int rc;
30830f2c99a4Syt160523
30840f2c99a4Syt160523 ADBG_TRACE(("ata_disk_set_feature_spinup entered\n"));
30850f2c99a4Syt160523
30860f2c99a4Syt160523 rc = ata_set_feature(ata_ctlp, ata_drvp, 0x07, 0);
30870f2c99a4Syt160523 if (!rc)
30880f2c99a4Syt160523 ata_pktp->ap_flags |= AP_ERROR;
30890f2c99a4Syt160523
30900f2c99a4Syt160523 return (ATA_FSM_RC_FINI);
30910f2c99a4Syt160523 }
30920f2c99a4Syt160523
30930f2c99a4Syt160523 /*
30940f2c99a4Syt160523 * Update device ata_id content - IDENTIFY DEVICE command.
30950f2c99a4Syt160523 */
30960f2c99a4Syt160523 static int
ata_disk_id_update(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)30970f2c99a4Syt160523 ata_disk_id_update(
30980f2c99a4Syt160523 ata_ctl_t *ata_ctlp,
30990f2c99a4Syt160523 ata_drv_t *ata_drvp,
31000f2c99a4Syt160523 ata_pkt_t *ata_pktp)
31010f2c99a4Syt160523 {
31020f2c99a4Syt160523 ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
31030f2c99a4Syt160523 caddr_t ioaddr1 = ata_ctlp->ac_ioaddr1;
31040f2c99a4Syt160523 ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
31050f2c99a4Syt160523 caddr_t ioaddr2 = ata_ctlp->ac_ioaddr2;
31060f2c99a4Syt160523 struct ata_id *aidp = &ata_drvp->ad_id;
31070f2c99a4Syt160523 int rc;
31080f2c99a4Syt160523
31090f2c99a4Syt160523 ADBG_TRACE(("ata_disk_id_update entered\n"));
31100f2c99a4Syt160523
31110f2c99a4Syt160523 /*
31120f2c99a4Syt160523 * select the appropriate drive and LUN
31130f2c99a4Syt160523 */
31140f2c99a4Syt160523 ddi_put8(io_hdl1, (uchar_t *)ioaddr1 + AT_DRVHD,
31150f2c99a4Syt160523 ata_drvp->ad_drive_bits);
31169f49ae27Smlf ata_nsecwait(400);
31170f2c99a4Syt160523
31180f2c99a4Syt160523 /*
31190f2c99a4Syt160523 * make certain the drive is selected, and wait for not busy
31200f2c99a4Syt160523 */
31210f2c99a4Syt160523 if (!ata_wait(io_hdl2, ioaddr2, ATS_DRDY, ATS_BSY, 5 * 1000000)) {
31220f2c99a4Syt160523 ADBG_ERROR(("ata_disk_id_update: select failed\n"));
31230f2c99a4Syt160523 ata_pktp->ap_flags |= AP_ERROR;
31240f2c99a4Syt160523 return (ATA_FSM_RC_FINI);
31250f2c99a4Syt160523 }
31260f2c99a4Syt160523
31270f2c99a4Syt160523 rc = ata_disk_id(io_hdl1, ioaddr1, io_hdl2, ioaddr2, aidp);
31280f2c99a4Syt160523
31290f2c99a4Syt160523 if (!rc) {
31300f2c99a4Syt160523 ata_pktp->ap_flags |= AP_ERROR;
31310f2c99a4Syt160523 } else {
31320f2c99a4Syt160523 swab(aidp->ai_drvser, aidp->ai_drvser,
31330f2c99a4Syt160523 sizeof (aidp->ai_drvser));
31340f2c99a4Syt160523 swab(aidp->ai_fw, aidp->ai_fw,
31350f2c99a4Syt160523 sizeof (aidp->ai_fw));
31360f2c99a4Syt160523 swab(aidp->ai_model, aidp->ai_model,
31370f2c99a4Syt160523 sizeof (aidp->ai_model));
31380f2c99a4Syt160523 }
31390f2c99a4Syt160523
31400f2c99a4Syt160523 return (ATA_FSM_RC_FINI);
31410f2c99a4Syt160523 }
31420f2c99a4Syt160523
31430f2c99a4Syt160523 /*
31440f2c99a4Syt160523 * Update device firmware.
31450f2c99a4Syt160523 */
31460f2c99a4Syt160523 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)31470f2c99a4Syt160523 ata_disk_update_fw(gtgt_t *gtgtp, ata_ctl_t *ata_ctlp,
31480f2c99a4Syt160523 ata_drv_t *ata_drvp, caddr_t fwfile,
31490f2c99a4Syt160523 uint_t size, uint8_t type, int flag)
31500f2c99a4Syt160523 {
31510f2c99a4Syt160523 ata_pkt_t *ata_pktp;
31520f2c99a4Syt160523 gcmd_t *gcmdp = NULL;
31530f2c99a4Syt160523 caddr_t fwfile_memp = NULL, tmp_fwfile_memp;
31540f2c99a4Syt160523 uint_t total_sec_count, sec_count, start_sec = 0;
31550f2c99a4Syt160523 uint8_t cmd_type;
31560f2c99a4Syt160523 int rc;
31570f2c99a4Syt160523
31580f2c99a4Syt160523 /*
31590f2c99a4Syt160523 * First check whether DOWNLOAD MICROCODE command is supported
31600f2c99a4Syt160523 */
31610f2c99a4Syt160523 if (!(ata_drvp->ad_id.ai_cmdset83 & 0x1)) {
31620f2c99a4Syt160523 ADBG_ERROR(("drive doesn't support download "
31630f2c99a4Syt160523 "microcode command\n"));
31640f2c99a4Syt160523 return (ENOTSUP);
31650f2c99a4Syt160523 }
31660f2c99a4Syt160523
31670f2c99a4Syt160523 switch (type) {
31680f2c99a4Syt160523 case FW_TYPE_TEMP:
31690f2c99a4Syt160523 cmd_type = ATCM_FW_TEMP;
31700f2c99a4Syt160523 break;
31710f2c99a4Syt160523
31720f2c99a4Syt160523 case FW_TYPE_PERM:
31730f2c99a4Syt160523 cmd_type = ATCM_FW_PERM;
31740f2c99a4Syt160523 break;
31750f2c99a4Syt160523
31760f2c99a4Syt160523 default:
31770f2c99a4Syt160523 return (EINVAL);
31780f2c99a4Syt160523 }
31790f2c99a4Syt160523
31800f2c99a4Syt160523 /* Temporary subcommand is obsolete in ATA/ATAPI-8 version */
31810f2c99a4Syt160523 if (cmd_type == ATCM_FW_TEMP) {
31820f2c99a4Syt160523 if (ata_drvp->ad_id.ai_majorversion & ATAC_MAJVER_8) {
31830f2c99a4Syt160523 ADBG_ERROR(("Temporary use is obsolete in "
31840f2c99a4Syt160523 "ATA/ATAPI-8 version\n"));
31850f2c99a4Syt160523 return (ENOTSUP);
31860f2c99a4Syt160523 }
31870f2c99a4Syt160523 }
31880f2c99a4Syt160523
31890f2c99a4Syt160523 total_sec_count = size >> SCTRSHFT;
31900f2c99a4Syt160523 if (total_sec_count > MAX_FWFILE_SIZE_ONECMD) {
31910f2c99a4Syt160523 if (cmd_type == ATCM_FW_TEMP) {
31920f2c99a4Syt160523 ADBG_ERROR(("firmware size: %x sectors is too large\n",
31930f2c99a4Syt160523 total_sec_count));
31940f2c99a4Syt160523 return (EINVAL);
31950f2c99a4Syt160523 } else {
31960f2c99a4Syt160523 ADBG_WARN(("firmware size: %x sectors is larger than"
31970f2c99a4Syt160523 " one command, need to use the multicommand"
31980f2c99a4Syt160523 " subcommand\n", total_sec_count));
31990f2c99a4Syt160523
32000f2c99a4Syt160523 cmd_type = ATCM_FW_MULTICMD;
32010f2c99a4Syt160523 if (!(ata_drvp->ad_id.ai_padding2[15] & 0x10)) {
32020f2c99a4Syt160523 ADBG_ERROR(("This drive doesn't support "
32030f2c99a4Syt160523 "the multicommand subcommand\n"));
32040f2c99a4Syt160523 return (ENOTSUP);
32050f2c99a4Syt160523 }
32060f2c99a4Syt160523 }
32070f2c99a4Syt160523 }
32080f2c99a4Syt160523
32090f2c99a4Syt160523 fwfile_memp = kmem_zalloc(size, KM_SLEEP);
32100f2c99a4Syt160523
32110f2c99a4Syt160523 if (ddi_copyin(fwfile, fwfile_memp, size, flag)) {
32120f2c99a4Syt160523 ADBG_ERROR(("ata_disk_update_fw copyin failed\n"));
32130f2c99a4Syt160523 rc = EFAULT;
32140f2c99a4Syt160523 goto done;
32150f2c99a4Syt160523 }
32160f2c99a4Syt160523
32170f2c99a4Syt160523 tmp_fwfile_memp = fwfile_memp;
32180f2c99a4Syt160523
32190f2c99a4Syt160523 for (; total_sec_count > 0; ) {
32200f2c99a4Syt160523 if ((gcmdp == NULL) && !(gcmdp =
32210f2c99a4Syt160523 ghd_gcmd_alloc(gtgtp, sizeof (*ata_pktp), TRUE))) {
32220f2c99a4Syt160523 ADBG_ERROR(("ata_disk_update_fw alloc failed\n"));
32230f2c99a4Syt160523 rc = ENOMEM;
32240f2c99a4Syt160523 goto done;
32250f2c99a4Syt160523 }
32260f2c99a4Syt160523
32270f2c99a4Syt160523 /* set the back ptr from the ata_pkt to the gcmd_t */
32280f2c99a4Syt160523 ata_pktp = GCMD2APKT(gcmdp);
32290f2c99a4Syt160523 ata_pktp->ap_gcmdp = gcmdp;
32300f2c99a4Syt160523 ata_pktp->ap_hd = ata_drvp->ad_drive_bits;
32310f2c99a4Syt160523 ata_pktp->ap_bytes_per_block = ata_drvp->ad_bytes_per_block;
32320f2c99a4Syt160523
32330f2c99a4Syt160523 /* use PIO mode to update disk firmware */
32340f2c99a4Syt160523 ata_pktp->ap_start = ata_disk_start_pio_out;
32350f2c99a4Syt160523 ata_pktp->ap_intr = ata_disk_intr_pio_out;
32360f2c99a4Syt160523 ata_pktp->ap_complete = NULL;
32370f2c99a4Syt160523
32380f2c99a4Syt160523 ata_pktp->ap_cmd = ATC_LOAD_FW;
32390f2c99a4Syt160523 /* use ap_bcount to set subcommand code */
32400f2c99a4Syt160523 ata_pktp->ap_bcount = (size_t)cmd_type;
32410f2c99a4Syt160523 ata_pktp->ap_pciide_dma = FALSE;
32420f2c99a4Syt160523 ata_pktp->ap_sg_cnt = 0;
32430f2c99a4Syt160523
32440f2c99a4Syt160523 sec_count = min(total_sec_count, MAX_FWFILE_SIZE_ONECMD);
32450f2c99a4Syt160523 ata_pktp->ap_flags = 0;
32460f2c99a4Syt160523
3247f304523cSzhongyan gu - Sun Microsystems - Beijing China ata_pktp->ap_count = (ushort_t)sec_count;
32480f2c99a4Syt160523 ata_pktp->ap_startsec = start_sec;
32490f2c99a4Syt160523 ata_pktp->ap_v_addr = tmp_fwfile_memp;
32500f2c99a4Syt160523 ata_pktp->ap_resid = sec_count << SCTRSHFT;
32510f2c99a4Syt160523
32520f2c99a4Syt160523 /* add it to the queue, and use POLL mode */
32530f2c99a4Syt160523 rc = ghd_transport(&ata_ctlp->ac_ccc, gcmdp, gcmdp->cmd_gtgtp,
32540f2c99a4Syt160523 ata_disk_updatefw_time, TRUE, NULL);
32550f2c99a4Syt160523
32560f2c99a4Syt160523 if (rc != TRAN_ACCEPT) {
32570f2c99a4Syt160523 /* this should never, ever happen */
32580f2c99a4Syt160523 rc = ENOTSUP;
32590f2c99a4Syt160523 goto done;
32600f2c99a4Syt160523 }
32610f2c99a4Syt160523
32620f2c99a4Syt160523 if (ata_pktp->ap_flags & AP_ERROR) {
32630f2c99a4Syt160523 if (ata_pktp->ap_error & ATE_ABORT) {
32640f2c99a4Syt160523 rc = ENOTSUP;
32650f2c99a4Syt160523 } else
32660f2c99a4Syt160523 rc = EIO;
32670f2c99a4Syt160523 goto done;
32680f2c99a4Syt160523
32690f2c99a4Syt160523 } else {
32700f2c99a4Syt160523 total_sec_count -= sec_count;
32710f2c99a4Syt160523 tmp_fwfile_memp += sec_count << SCTRSHFT;
32720f2c99a4Syt160523 start_sec += sec_count;
32730f2c99a4Syt160523 }
32740f2c99a4Syt160523 }
32750f2c99a4Syt160523
32760f2c99a4Syt160523 rc = 0;
32770f2c99a4Syt160523 done:
32780f2c99a4Syt160523 if (gcmdp != NULL)
32790f2c99a4Syt160523 ghd_gcmd_free(gcmdp);
32800f2c99a4Syt160523
32810f2c99a4Syt160523 kmem_free(fwfile_memp, size);
32820f2c99a4Syt160523
32830f2c99a4Syt160523 return (rc);
32840f2c99a4Syt160523 }
3285