1507c3241Smlf /*
2507c3241Smlf * CDDL HEADER START
3507c3241Smlf *
4507c3241Smlf * The contents of this file are subject to the terms of the
5d39757aaSmlf * 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 /*
230f1b305eSSeth Goldberg * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24507c3241Smlf * Use is subject to license terms.
25*6e6c7d67SAndrew Stormont *
26*6e6c7d67SAndrew Stormont * Copyright 2018 RackTop Systems.
27507c3241Smlf */
28507c3241Smlf
29507c3241Smlf #include <sys/types.h>
30507c3241Smlf #include <sys/modctl.h>
31507c3241Smlf #include <sys/debug.h>
32507c3241Smlf #include <sys/promif.h>
33507c3241Smlf #include <sys/pci.h>
34507c3241Smlf #include <sys/errno.h>
35507c3241Smlf #include <sys/open.h>
36507c3241Smlf #include <sys/uio.h>
37507c3241Smlf #include <sys/cred.h>
389f49ae27Smlf #include <sys/cpu.h>
39507c3241Smlf #include "ata_common.h"
40507c3241Smlf #include "ata_disk.h"
41507c3241Smlf #include "atapi.h"
42507c3241Smlf #include "ata_blacklist.h"
43507c3241Smlf #include "sil3xxx.h"
44507c3241Smlf
45507c3241Smlf /*
46507c3241Smlf * Solaris Entry Points.
47507c3241Smlf */
48507c3241Smlf
49507c3241Smlf static int ata_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
50507c3241Smlf static int ata_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
51507c3241Smlf static int ata_bus_ctl(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t o,
52507c3241Smlf void *a, void *v);
53507c3241Smlf static uint_t ata_intr(caddr_t arg);
54507c3241Smlf
55507c3241Smlf /*
56507c3241Smlf * GHD Entry points
57507c3241Smlf */
58507c3241Smlf
59507c3241Smlf static int ata_get_status(void *hba_handle, void *intr_status);
60507c3241Smlf static void ata_process_intr(void *hba_handle, void *intr_status);
61507c3241Smlf static int ata_hba_start(void *handle, gcmd_t *gcmdp);
62507c3241Smlf static void ata_hba_complete(void *handle, gcmd_t *gcmdp, int do_callback);
63507c3241Smlf static int ata_timeout_func(void *hba_handle, gcmd_t *gcmdp,
64507c3241Smlf gtgt_t *gtgtp, gact_t action, int calltype);
65507c3241Smlf
66507c3241Smlf /*
67507c3241Smlf * Local Function Prototypes
68507c3241Smlf */
69507c3241Smlf static int ata_prop_lookup_int(dev_t match_dev, dev_info_t *dip,
70507c3241Smlf uint_t flags, char *name, int defvalue);
71507c3241Smlf static int ata_ctlr_fsm(uchar_t fsm_func, ata_ctl_t *ata_ctlp,
72507c3241Smlf ata_drv_t *ata_drvp, ata_pkt_t *ata_pktp,
73507c3241Smlf int *DoneFlgp);
74507c3241Smlf static void ata_destroy_controller(dev_info_t *dip);
75507c3241Smlf static int ata_drive_type(uchar_t drvhd,
76507c3241Smlf ddi_acc_handle_t io_hdl1, caddr_t ioaddr1,
77507c3241Smlf ddi_acc_handle_t io_hdl2, caddr_t ioaddr2,
78507c3241Smlf struct ata_id *ata_id_bufp);
79507c3241Smlf static ata_ctl_t *ata_init_controller(dev_info_t *dip);
80507c3241Smlf static ata_drv_t *ata_init_drive(ata_ctl_t *ata_ctlp,
81507c3241Smlf uchar_t targ, uchar_t lun);
82507c3241Smlf static int ata_init_drive_pcidma(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
83507c3241Smlf dev_info_t *tdip);
84507c3241Smlf static int ata_flush_cache(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp);
85507c3241Smlf static void ata_init_pciide(dev_info_t *dip, ata_ctl_t *ata_ctlp);
86507c3241Smlf static int ata_reset_bus(ata_ctl_t *ata_ctlp);
87507c3241Smlf static int ata_setup_ioaddr(dev_info_t *dip,
88507c3241Smlf ddi_acc_handle_t *iohandle1, caddr_t *ioaddr1p,
89507c3241Smlf ddi_acc_handle_t *iohandle2, caddr_t *ioaddr2p,
90507c3241Smlf ddi_acc_handle_t *bm_hdlp, caddr_t *bm_addrp);
91507c3241Smlf static int ata_software_reset(ata_ctl_t *ata_ctlp);
92507c3241Smlf static int ata_start_arq(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp,
93507c3241Smlf ata_pkt_t *ata_pktp);
94507c3241Smlf static int ata_strncmp(char *p1, char *p2, int cnt);
95507c3241Smlf static void ata_uninit_drive(ata_drv_t *ata_drvp);
96507c3241Smlf
97507c3241Smlf static int ata_check_pciide_blacklist(dev_info_t *dip, uint_t flags);
98507c3241Smlf static int ata_check_revert_to_defaults(ata_drv_t *ata_drvp);
99507c3241Smlf static void ata_show_transfer_mode(ata_ctl_t *, ata_drv_t *);
100507c3241Smlf static int ata_spec_init_controller(dev_info_t *dip);
101507c3241Smlf
1022df1fe9cSrandyf static void ata_init_pm(dev_info_t *);
1032df1fe9cSrandyf static int ata_suspend(dev_info_t *);
1042df1fe9cSrandyf static int ata_resume(dev_info_t *);
1052df1fe9cSrandyf static int ata_power(dev_info_t *, int, int);
1062df1fe9cSrandyf static int ata_change_power(dev_info_t *, uint8_t);
1072df1fe9cSrandyf static int ata_is_pci(dev_info_t *);
1085fb86baeSml static void ata_disable_DMA(ata_drv_t *ata_drvp);
109fe072f42SAda static int ata_check_dma_mode(ata_drv_t *ata_drvp);
110507c3241Smlf
111507c3241Smlf /*
112507c3241Smlf * Local static data
113507c3241Smlf */
114507c3241Smlf static void *ata_state;
115507c3241Smlf
116507c3241Smlf static tmr_t ata_timer_conf; /* single timeout list for all instances */
117507c3241Smlf static int ata_watchdog_usec = 100000; /* check timeouts every 100 ms */
118507c3241Smlf
119507c3241Smlf int ata_hba_start_watchdog = 1000;
120507c3241Smlf int ata_process_intr_watchdog = 1000;
121507c3241Smlf int ata_reset_bus_watchdog = 1000;
122507c3241Smlf
123507c3241Smlf
1242df1fe9cSrandyf /*
1252df1fe9cSrandyf * Use local or framework power management
1262df1fe9cSrandyf */
1272df1fe9cSrandyf
1282df1fe9cSrandyf #ifdef ATA_USE_AUTOPM
1292df1fe9cSrandyf #define ATA_BUSY_COMPONENT(d, c) ((void)pm_busy_component(d, c))
1302df1fe9cSrandyf #define ATA_IDLE_COMPONENT(d, c) ((void)pm_idle_component(d, c))
1312df1fe9cSrandyf #define ATA_RAISE_POWER(d, c, l) pm_raise_power(d, c, l)
1322df1fe9cSrandyf #define ATA_LOWER_POWER(d, c, l) pm_lower_power(d, c, l)
1332df1fe9cSrandyf #else
1342df1fe9cSrandyf #define ATA_BUSY_COMPONENT(d, c)
1352df1fe9cSrandyf #define ATA_IDLE_COMPONENT(d, c)
1362df1fe9cSrandyf #define ATA_RAISE_POWER(d, c, l) ata_power(d, c, l)
1372df1fe9cSrandyf #define ATA_LOWER_POWER(d, c, l) ata_power(d, c, l)
1382df1fe9cSrandyf #endif
139507c3241Smlf /*
140507c3241Smlf * number of seconds to wait during various operations
141507c3241Smlf */
142507c3241Smlf int ata_flush_delay = 5 * 1000000;
143507c3241Smlf uint_t ata_set_feature_wait = 4 * 1000000;
144507c3241Smlf uint_t ata_flush_cache_wait = 60 * 1000000; /* may take a long time */
145507c3241Smlf
146507c3241Smlf /*
147507c3241Smlf * Change this for SFF-8070i support. Currently SFF-8070i is
148507c3241Smlf * using a field in the IDENTIFY PACKET DEVICE response which
149507c3241Smlf * already seems to be in use by some vendor's drives. I suspect
150507c3241Smlf * SFF will either move their laslun field or provide a reliable
151507c3241Smlf * way to validate it.
152507c3241Smlf */
153507c3241Smlf int ata_enable_atapi_luns = FALSE;
154507c3241Smlf
155507c3241Smlf /*
156507c3241Smlf * set this to disable all DMA requests
157507c3241Smlf */
158507c3241Smlf int ata_dma_disabled = FALSE;
159507c3241Smlf
160507c3241Smlf /*
161507c3241Smlf * set this to TRUE to enable storing the IDENTIFY DEVICE result in the
162507c3241Smlf * "ata" or "atapi" property.
163507c3241Smlf */
164507c3241Smlf int ata_id_debug = FALSE;
165507c3241Smlf
166507c3241Smlf /*
167507c3241Smlf * set this to TRUE to enable logging device-capability data
168507c3241Smlf */
169507c3241Smlf int ata_capability_data = FALSE;
170507c3241Smlf
171507c3241Smlf /*
172507c3241Smlf * DMA selection message pointers
173507c3241Smlf */
174507c3241Smlf char *ata_cntrl_DMA_sel_msg;
175507c3241Smlf char *ata_dev_DMA_sel_msg;
176507c3241Smlf
177507c3241Smlf /*
178507c3241Smlf * bus nexus operations
179507c3241Smlf */
180507c3241Smlf static struct bus_ops ata_bus_ops;
181507c3241Smlf static struct bus_ops *scsa_bus_ops_p;
182507c3241Smlf
183507c3241Smlf /* ARGSUSED */
184507c3241Smlf static int
ata_open(dev_t * devp,int flag,int otyp,cred_t * cred_p)185507c3241Smlf ata_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
186507c3241Smlf {
187507c3241Smlf if (ddi_get_soft_state(ata_state, getminor(*devp)) == NULL)
188507c3241Smlf return (ENXIO);
189507c3241Smlf
190507c3241Smlf return (0);
191507c3241Smlf }
192507c3241Smlf
193507c3241Smlf /*
194507c3241Smlf * The purpose of this function is to pass the ioaddress of the controller
195507c3241Smlf * to the caller, specifically used for upgrade from pre-pciide
196507c3241Smlf * to pciide nodes
197507c3241Smlf */
198507c3241Smlf /* ARGSUSED */
199507c3241Smlf static int
ata_read(dev_t dev,struct uio * uio_p,cred_t * cred_p)200507c3241Smlf ata_read(dev_t dev, struct uio *uio_p, cred_t *cred_p)
201507c3241Smlf {
202507c3241Smlf ata_ctl_t *ata_ctlp;
203507c3241Smlf char buf[18];
204507c3241Smlf long len;
205507c3241Smlf
206507c3241Smlf ata_ctlp = ddi_get_soft_state(ata_state, getminor(dev));
207507c3241Smlf
208507c3241Smlf if (ata_ctlp == NULL)
209507c3241Smlf return (ENXIO);
210507c3241Smlf
211507c3241Smlf (void) sprintf(buf, "%p\n", (void *) ata_ctlp->ac_ioaddr1);
212507c3241Smlf
213507c3241Smlf len = strlen(buf) - uio_p->uio_offset;
214507c3241Smlf len = min(uio_p->uio_resid, len);
215507c3241Smlf if (len <= 0)
216507c3241Smlf return (0);
217507c3241Smlf
218507c3241Smlf return (uiomove((caddr_t)(buf + uio_p->uio_offset), len,
219507c3241Smlf UIO_READ, uio_p));
220507c3241Smlf }
221507c3241Smlf
222507c3241Smlf int
ata_devo_reset(dev_info_t * dip,ddi_reset_cmd_t cmd)223507c3241Smlf ata_devo_reset(
224507c3241Smlf dev_info_t *dip,
225507c3241Smlf ddi_reset_cmd_t cmd)
226507c3241Smlf {
227507c3241Smlf ata_ctl_t *ata_ctlp;
228507c3241Smlf ata_drv_t *ata_drvp;
229507c3241Smlf int instance;
230507c3241Smlf int i;
231507c3241Smlf int rc;
232507c3241Smlf int flush_okay;
233507c3241Smlf
234507c3241Smlf if (cmd != DDI_RESET_FORCE)
235507c3241Smlf return (0);
236507c3241Smlf
237507c3241Smlf instance = ddi_get_instance(dip);
238507c3241Smlf ata_ctlp = ddi_get_soft_state(ata_state, instance);
239507c3241Smlf
240507c3241Smlf if (!ata_ctlp)
241507c3241Smlf return (0);
242507c3241Smlf
243507c3241Smlf /*
244507c3241Smlf * reset ATA drives and flush the write cache of any drives
245507c3241Smlf */
246507c3241Smlf flush_okay = TRUE;
247507c3241Smlf for (i = 0; i < ATA_MAXTARG; i++) {
248507c3241Smlf if ((ata_drvp = CTL2DRV(ata_ctlp, i, 0)) == 0)
249507c3241Smlf continue;
250507c3241Smlf /* Don't revert to defaults for certain IBM drives */
251507c3241Smlf if ((ata_drvp->ad_flags & AD_DISK) != 0 &&
252507c3241Smlf ((ata_drvp->ad_flags & AD_NORVRT) == 0)) {
253507c3241Smlf /* Enable revert to defaults when reset */
2542df1fe9cSrandyf (void) ata_set_feature(ata_ctlp, ata_drvp,
2552df1fe9cSrandyf ATSF_ENA_REVPOD, 0);
256507c3241Smlf }
257507c3241Smlf
258507c3241Smlf /*
259507c3241Smlf * skip flush cache if device type is cdrom
260507c3241Smlf *
261507c3241Smlf * notes: the structure definitions for ata_drvp->ad_id are
262507c3241Smlf * defined for the ATA IDENTIFY_DEVICE, but if AD_ATAPI is set
263507c3241Smlf * the struct holds data for the ATAPI IDENTIFY_PACKET_DEVICE
264507c3241Smlf */
265507c3241Smlf if (!IS_CDROM(ata_drvp)) {
266507c3241Smlf
267507c3241Smlf /*
268507c3241Smlf * Try the ATA/ATAPI flush write cache command
269507c3241Smlf */
270507c3241Smlf rc = ata_flush_cache(ata_ctlp, ata_drvp);
271507c3241Smlf ADBG_WARN(("ata_flush_cache %s\n",
2722df1fe9cSrandyf rc ? "okay" : "failed"));
273507c3241Smlf
274507c3241Smlf if (!rc)
275507c3241Smlf flush_okay = FALSE;
276507c3241Smlf }
277507c3241Smlf
278507c3241Smlf
279507c3241Smlf /*
280507c3241Smlf * do something else if flush cache not supported
281507c3241Smlf */
282507c3241Smlf }
283507c3241Smlf
284507c3241Smlf /*
285507c3241Smlf * just busy wait if any drive doesn't support FLUSH CACHE
286507c3241Smlf */
287507c3241Smlf if (!flush_okay)
288507c3241Smlf drv_usecwait(ata_flush_delay);
289507c3241Smlf return (0);
290507c3241Smlf }
291507c3241Smlf
29219397407SSherry Moore /*
29319397407SSherry Moore * quiesce(9E) entry point.
29419397407SSherry Moore *
29519397407SSherry Moore * This function is called when the system is single-threaded at high
29619397407SSherry Moore * PIL with preemption disabled. Therefore, this function must not be
29719397407SSherry Moore * blocked.
29819397407SSherry Moore *
29919397407SSherry Moore * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
30019397407SSherry Moore * DDI_FAILURE indicates an error condition and should almost never happen.
30119397407SSherry Moore */
30219397407SSherry Moore int
ata_quiesce(dev_info_t * dip)30319397407SSherry Moore ata_quiesce(dev_info_t *dip)
30419397407SSherry Moore {
30519397407SSherry Moore #ifdef ATA_DEBUG
30619397407SSherry Moore /*
30719397407SSherry Moore * Turn off debugging
30819397407SSherry Moore */
30919397407SSherry Moore ata_debug = 0;
31019397407SSherry Moore #endif
31119397407SSherry Moore
31219397407SSherry Moore return (ata_devo_reset(dip, DDI_RESET_FORCE));
31319397407SSherry Moore }
31419397407SSherry Moore
315507c3241Smlf
316507c3241Smlf static struct cb_ops ata_cb_ops = {
317507c3241Smlf ata_open, /* open */
318507c3241Smlf nulldev, /* close */
319507c3241Smlf nodev, /* strategy */
320507c3241Smlf nodev, /* print */
321507c3241Smlf nodev, /* dump */
322507c3241Smlf ata_read, /* read */
323507c3241Smlf nodev, /* write */
324507c3241Smlf nodev, /* ioctl */
325507c3241Smlf nodev, /* devmap */
326507c3241Smlf nodev, /* mmap */
327507c3241Smlf nodev, /* segmap */
328507c3241Smlf nochpoll, /* chpoll */
329507c3241Smlf ddi_prop_op, /* prop_op */
330507c3241Smlf NULL, /* stream info */
331507c3241Smlf D_MP, /* driver compatibility flag */
332507c3241Smlf CB_REV, /* cb_ops revision */
333507c3241Smlf nodev, /* aread */
334507c3241Smlf nodev /* awrite */
335507c3241Smlf };
336507c3241Smlf
337507c3241Smlf static struct dev_ops ata_ops = {
338507c3241Smlf DEVO_REV, /* devo_rev, */
339507c3241Smlf 0, /* refcnt */
340507c3241Smlf ddi_getinfo_1to1, /* info */
341507c3241Smlf nulldev, /* identify */
342b3c0e203Smlf NULL, /* probe */
343507c3241Smlf ata_attach, /* attach */
344507c3241Smlf ata_detach, /* detach */
345507c3241Smlf ata_devo_reset, /* reset */
346507c3241Smlf &ata_cb_ops, /* driver operations */
3472df1fe9cSrandyf NULL, /* bus operations */
34819397407SSherry Moore ata_power, /* power */
34919397407SSherry Moore ata_quiesce /* quiesce */
350507c3241Smlf };
351507c3241Smlf
352507c3241Smlf /* driver loadable module wrapper */
353507c3241Smlf static struct modldrv modldrv = {
354507c3241Smlf &mod_driverops, /* Type of module. This one is a driver */
355507c3241Smlf "ATA AT-bus attachment disk controller Driver", /* module name */
356507c3241Smlf &ata_ops, /* driver ops */
357507c3241Smlf };
358507c3241Smlf
359507c3241Smlf static struct modlinkage modlinkage = {
360507c3241Smlf MODREV_1, (void *)&modldrv, NULL
361507c3241Smlf };
362507c3241Smlf
363507c3241Smlf #ifdef ATA_DEBUG
364507c3241Smlf int ata_debug_init = FALSE;
365507c3241Smlf int ata_debug_attach = FALSE;
366507c3241Smlf
367507c3241Smlf int ata_debug = ADBG_FLAG_ERROR
368507c3241Smlf /* | ADBG_FLAG_ARQ */
369507c3241Smlf /* | ADBG_FLAG_INIT */
370507c3241Smlf /* | ADBG_FLAG_TRACE */
371507c3241Smlf /* | ADBG_FLAG_TRANSPORT */
372507c3241Smlf /* | ADBG_FLAG_WARN */
373507c3241Smlf ;
374507c3241Smlf #endif
375507c3241Smlf
376507c3241Smlf int
_init(void)377507c3241Smlf _init(void)
378507c3241Smlf {
379507c3241Smlf int err;
380507c3241Smlf
381507c3241Smlf #ifdef ATA_DEBUG
382507c3241Smlf if (ata_debug_init)
383507c3241Smlf debug_enter("\nATA _INIT\n");
384507c3241Smlf #endif
385507c3241Smlf
386507c3241Smlf if ((err = ddi_soft_state_init(&ata_state, sizeof (ata_ctl_t), 0)) != 0)
387507c3241Smlf return (err);
388507c3241Smlf
389507c3241Smlf if ((err = scsi_hba_init(&modlinkage)) != 0) {
390507c3241Smlf ddi_soft_state_fini(&ata_state);
391507c3241Smlf return (err);
392507c3241Smlf }
393507c3241Smlf
394507c3241Smlf /* save pointer to SCSA provided bus_ops struct */
395507c3241Smlf scsa_bus_ops_p = ata_ops.devo_bus_ops;
396507c3241Smlf
397507c3241Smlf /* make a copy of SCSA bus_ops */
398507c3241Smlf ata_bus_ops = *(ata_ops.devo_bus_ops);
399507c3241Smlf
400507c3241Smlf /*
401507c3241Smlf * Modify our bus_ops to call our routines. Our implementation
402507c3241Smlf * will determine if the device is ATA or ATAPI/SCSA and react
403507c3241Smlf * accordingly.
404507c3241Smlf */
405507c3241Smlf ata_bus_ops.bus_ctl = ata_bus_ctl;
406507c3241Smlf
407507c3241Smlf /* patch our bus_ops into the dev_ops struct */
408507c3241Smlf ata_ops.devo_bus_ops = &ata_bus_ops;
409507c3241Smlf
410507c3241Smlf if ((err = mod_install(&modlinkage)) != 0) {
411507c3241Smlf scsi_hba_fini(&modlinkage);
412507c3241Smlf ddi_soft_state_fini(&ata_state);
413507c3241Smlf }
414507c3241Smlf
415507c3241Smlf /*
416507c3241Smlf * Initialize the per driver timer info.
417507c3241Smlf */
418507c3241Smlf
419507c3241Smlf ghd_timer_init(&ata_timer_conf, drv_usectohz(ata_watchdog_usec));
420507c3241Smlf
421507c3241Smlf return (err);
422507c3241Smlf }
423507c3241Smlf
424507c3241Smlf int
_fini(void)425507c3241Smlf _fini(void)
426507c3241Smlf {
427507c3241Smlf int err;
428507c3241Smlf
429507c3241Smlf if ((err = mod_remove(&modlinkage)) == 0) {
430507c3241Smlf ghd_timer_fini(&ata_timer_conf);
431507c3241Smlf scsi_hba_fini(&modlinkage);
432507c3241Smlf ddi_soft_state_fini(&ata_state);
433507c3241Smlf }
434507c3241Smlf
435507c3241Smlf return (err);
436507c3241Smlf }
437507c3241Smlf
438507c3241Smlf int
_info(struct modinfo * modinfop)439507c3241Smlf _info(struct modinfo *modinfop)
440507c3241Smlf {
441507c3241Smlf return (mod_info(&modlinkage, modinfop));
442507c3241Smlf }
443507c3241Smlf
444507c3241Smlf
445507c3241Smlf /*
446507c3241Smlf *
447507c3241Smlf * driver attach entry point
448507c3241Smlf *
449507c3241Smlf */
450507c3241Smlf
451507c3241Smlf static int
ata_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)452507c3241Smlf ata_attach(
453507c3241Smlf dev_info_t *dip,
454507c3241Smlf ddi_attach_cmd_t cmd)
455507c3241Smlf {
456507c3241Smlf ata_ctl_t *ata_ctlp;
457507c3241Smlf ata_drv_t *ata_drvp;
458507c3241Smlf ata_drv_t *first_drvp = NULL;
459507c3241Smlf uchar_t targ;
460507c3241Smlf uchar_t lun;
461507c3241Smlf uchar_t lastlun;
462507c3241Smlf int atapi_count = 0;
463507c3241Smlf int disk_count = 0;
464507c3241Smlf
465507c3241Smlf ADBG_TRACE(("ata_attach entered\n"));
466507c3241Smlf #ifdef ATA_DEBUG
467507c3241Smlf if (ata_debug_attach)
468507c3241Smlf debug_enter("\nATA_ATTACH\n\n");
469507c3241Smlf #endif
470507c3241Smlf
4712df1fe9cSrandyf switch (cmd) {
4722df1fe9cSrandyf case DDI_ATTACH:
4732df1fe9cSrandyf break;
4742df1fe9cSrandyf case DDI_RESUME:
4752df1fe9cSrandyf return (ata_resume(dip));
4762df1fe9cSrandyf default:
477507c3241Smlf return (DDI_FAILURE);
4782df1fe9cSrandyf }
479507c3241Smlf
480507c3241Smlf /* initialize controller */
481507c3241Smlf ata_ctlp = ata_init_controller(dip);
482507c3241Smlf
483507c3241Smlf if (ata_ctlp == NULL)
484507c3241Smlf goto errout;
485507c3241Smlf
486507c3241Smlf mutex_enter(&ata_ctlp->ac_ccc.ccc_hba_mutex);
487507c3241Smlf
488507c3241Smlf /* initialize drives */
489507c3241Smlf
490507c3241Smlf for (targ = 0; targ < ATA_MAXTARG; targ++) {
491507c3241Smlf
492507c3241Smlf ata_drvp = ata_init_drive(ata_ctlp, targ, 0);
493507c3241Smlf if (ata_drvp == NULL)
494507c3241Smlf continue;
495507c3241Smlf
496507c3241Smlf if (first_drvp == NULL)
497507c3241Smlf first_drvp = ata_drvp;
498507c3241Smlf
499507c3241Smlf if (ATAPIDRV(ata_drvp)) {
500507c3241Smlf atapi_count++;
501507c3241Smlf lastlun = ata_drvp->ad_id.ai_lastlun;
502507c3241Smlf } else {
503507c3241Smlf disk_count++;
504507c3241Smlf lastlun = 0;
505507c3241Smlf }
506507c3241Smlf
507507c3241Smlf /*
508507c3241Smlf * LUN support is currently disabled. Check with SFF-8070i
509507c3241Smlf * before enabling.
510507c3241Smlf */
511507c3241Smlf if (!ata_enable_atapi_luns)
512507c3241Smlf lastlun = 0;
513507c3241Smlf
514507c3241Smlf /* Initialize higher LUNs, if there are any */
515507c3241Smlf for (lun = 1; lun <= lastlun && lun < ATA_MAXLUN; lun++) {
516507c3241Smlf if ((ata_drvp =
517507c3241Smlf ata_init_drive(ata_ctlp, targ, lun)) != NULL) {
518507c3241Smlf ata_show_transfer_mode(ata_ctlp, ata_drvp);
519507c3241Smlf }
520507c3241Smlf }
521507c3241Smlf }
522507c3241Smlf
523507c3241Smlf if ((atapi_count == 0) && (disk_count == 0)) {
524507c3241Smlf ADBG_WARN(("ata_attach: no drives detected\n"));
525507c3241Smlf goto errout1;
526507c3241Smlf }
527507c3241Smlf
528507c3241Smlf /*
529507c3241Smlf * Always make certain that a valid drive is selected so
530507c3241Smlf * that routines which poll the status register don't get
531507c3241Smlf * confused by non-existent drives.
532507c3241Smlf */
533507c3241Smlf ddi_put8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_drvhd,
5342df1fe9cSrandyf first_drvp->ad_drive_bits);
5359f49ae27Smlf ata_nsecwait(400);
536507c3241Smlf
537507c3241Smlf /*
538507c3241Smlf * make certain the drive selected
539507c3241Smlf */
540507c3241Smlf if (!ata_wait(ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2,
5412df1fe9cSrandyf 0, ATS_BSY, 5000000)) {
542507c3241Smlf ADBG_ERROR(("ata_attach: select failed\n"));
543507c3241Smlf }
544507c3241Smlf
545507c3241Smlf /*
546507c3241Smlf * initialize atapi/ata_dsk modules if we have at least
547507c3241Smlf * one drive of that type.
548507c3241Smlf */
549507c3241Smlf
550507c3241Smlf if (atapi_count) {
551507c3241Smlf if (!atapi_attach(ata_ctlp))
552507c3241Smlf goto errout1;
553507c3241Smlf ata_ctlp->ac_flags |= AC_ATAPI_INIT;
554507c3241Smlf }
555507c3241Smlf
556507c3241Smlf if (disk_count) {
557507c3241Smlf if (!ata_disk_attach(ata_ctlp))
558507c3241Smlf goto errout1;
559507c3241Smlf ata_ctlp->ac_flags |= AC_DISK_INIT;
560507c3241Smlf }
561507c3241Smlf
562507c3241Smlf /*
563507c3241Smlf * make certain the interrupt and error latches are clear
564507c3241Smlf */
565507c3241Smlf if (ata_ctlp->ac_pciide) {
566507c3241Smlf
567507c3241Smlf int instance = ddi_get_instance(dip);
568507c3241Smlf if (ddi_create_minor_node(dip, "control", S_IFCHR, instance,
569507c3241Smlf DDI_PSEUDO, 0) != DDI_SUCCESS) {
570507c3241Smlf goto errout1;
571507c3241Smlf }
572507c3241Smlf
573507c3241Smlf (void) ata_pciide_status_clear(ata_ctlp);
574507c3241Smlf
575507c3241Smlf }
576507c3241Smlf
577507c3241Smlf /*
578507c3241Smlf * enable the interrupt handler and drop the mutex
579507c3241Smlf */
580507c3241Smlf ata_ctlp->ac_flags |= AC_ATTACHED;
581507c3241Smlf mutex_exit(&ata_ctlp->ac_ccc.ccc_hba_mutex);
582507c3241Smlf
5832df1fe9cSrandyf ata_init_pm(dip);
5842df1fe9cSrandyf
585507c3241Smlf ddi_report_dev(dip);
586507c3241Smlf return (DDI_SUCCESS);
587507c3241Smlf
588507c3241Smlf errout1:
589507c3241Smlf mutex_exit(&ata_ctlp->ac_ccc.ccc_hba_mutex);
590507c3241Smlf errout:
591507c3241Smlf (void) ata_detach(dip, DDI_DETACH);
592507c3241Smlf return (DDI_FAILURE);
593507c3241Smlf }
594507c3241Smlf
595507c3241Smlf /* driver detach entry point */
596507c3241Smlf
597507c3241Smlf static int
ata_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)598507c3241Smlf ata_detach(
599507c3241Smlf dev_info_t *dip,
600507c3241Smlf ddi_detach_cmd_t cmd)
601507c3241Smlf {
602507c3241Smlf ata_ctl_t *ata_ctlp;
603507c3241Smlf ata_drv_t *ata_drvp;
604507c3241Smlf int instance;
605507c3241Smlf int i;
606507c3241Smlf int j;
607507c3241Smlf
608507c3241Smlf ADBG_TRACE(("ata_detach entered\n"));
609507c3241Smlf
6102df1fe9cSrandyf switch (cmd) {
6112df1fe9cSrandyf case DDI_DETACH:
6122df1fe9cSrandyf break;
6132df1fe9cSrandyf case DDI_SUSPEND:
6142df1fe9cSrandyf return (ata_suspend(dip));
6152df1fe9cSrandyf default:
616507c3241Smlf return (DDI_FAILURE);
6172df1fe9cSrandyf }
618507c3241Smlf
619507c3241Smlf instance = ddi_get_instance(dip);
620507c3241Smlf ata_ctlp = ddi_get_soft_state(ata_state, instance);
621507c3241Smlf
622507c3241Smlf if (!ata_ctlp)
623507c3241Smlf return (DDI_SUCCESS);
624507c3241Smlf
6252df1fe9cSrandyf if (ata_ctlp->ac_pm_support) {
6262df1fe9cSrandyf ATA_BUSY_COMPONENT(dip, 0);
6272df1fe9cSrandyf if (ata_ctlp->ac_pm_level != PM_LEVEL_D0) {
6282df1fe9cSrandyf if (ATA_RAISE_POWER(dip, 0, PM_LEVEL_D0) !=
6292df1fe9cSrandyf DDI_SUCCESS) {
6302df1fe9cSrandyf ATA_IDLE_COMPONENT(dip, 0);
6312df1fe9cSrandyf return (DDI_FAILURE);
6322df1fe9cSrandyf }
6332df1fe9cSrandyf }
6342df1fe9cSrandyf (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-components");
6352df1fe9cSrandyf }
636507c3241Smlf ata_ctlp->ac_flags &= ~AC_ATTACHED;
637507c3241Smlf
638507c3241Smlf /* destroy ata module */
639507c3241Smlf if (ata_ctlp->ac_flags & AC_DISK_INIT)
640507c3241Smlf ata_disk_detach(ata_ctlp);
641507c3241Smlf
642507c3241Smlf /* destroy atapi module */
643507c3241Smlf if (ata_ctlp->ac_flags & AC_ATAPI_INIT)
644507c3241Smlf atapi_detach(ata_ctlp);
645507c3241Smlf
646507c3241Smlf ddi_remove_minor_node(dip, NULL);
647507c3241Smlf
648507c3241Smlf /* destroy drives */
649507c3241Smlf for (i = 0; i < ATA_MAXTARG; i++) {
650507c3241Smlf for (j = 0; j < ATA_MAXLUN; j++) {
651507c3241Smlf ata_drvp = CTL2DRV(ata_ctlp, i, j);
652507c3241Smlf if (ata_drvp != NULL)
653507c3241Smlf ata_uninit_drive(ata_drvp);
654507c3241Smlf }
655507c3241Smlf }
656507c3241Smlf
657507c3241Smlf if (ata_ctlp->ac_iohandle1)
658507c3241Smlf ddi_regs_map_free(&ata_ctlp->ac_iohandle1);
659507c3241Smlf if (ata_ctlp->ac_iohandle2)
660507c3241Smlf ddi_regs_map_free(&ata_ctlp->ac_iohandle2);
661507c3241Smlf if (ata_ctlp->ac_bmhandle)
662507c3241Smlf ddi_regs_map_free(&ata_ctlp->ac_bmhandle);
663507c3241Smlf
664507c3241Smlf /* destroy controller */
665507c3241Smlf ata_destroy_controller(dip);
666507c3241Smlf
667b3c0e203Smlf ddi_prop_remove_all(dip);
668b3c0e203Smlf
669507c3241Smlf return (DDI_SUCCESS);
670507c3241Smlf }
671507c3241Smlf
672507c3241Smlf /*
673507c3241Smlf * Nexus driver bus_ctl entry point
674507c3241Smlf */
675507c3241Smlf /*ARGSUSED*/
676507c3241Smlf static int
ata_bus_ctl(dev_info_t * d,dev_info_t * r,ddi_ctl_enum_t o,void * a,void * v)677507c3241Smlf ata_bus_ctl(
678507c3241Smlf dev_info_t *d,
679507c3241Smlf dev_info_t *r,
680507c3241Smlf ddi_ctl_enum_t o,
681507c3241Smlf void *a,
682507c3241Smlf void *v)
683507c3241Smlf {
684507c3241Smlf dev_info_t *tdip;
685507c3241Smlf int target_type;
686507c3241Smlf int rc;
687507c3241Smlf char *bufp;
688507c3241Smlf
689507c3241Smlf ADBG_TRACE(("ata_bus_ctl entered\n"));
690507c3241Smlf
691507c3241Smlf switch (o) {
692507c3241Smlf
693507c3241Smlf case DDI_CTLOPS_SIDDEV:
694507c3241Smlf return (DDI_FAILURE);
695507c3241Smlf
696507c3241Smlf case DDI_CTLOPS_IOMIN:
697507c3241Smlf
698507c3241Smlf /*
699507c3241Smlf * Since we use PIO, we return a minimum I/O size of
700507c3241Smlf * one byte. This will need to be updated when we
701507c3241Smlf * implement DMA support
702507c3241Smlf */
703507c3241Smlf
704507c3241Smlf *((int *)v) = 1;
705507c3241Smlf return (DDI_SUCCESS);
706507c3241Smlf
707507c3241Smlf case DDI_CTLOPS_DMAPMAPC:
708507c3241Smlf case DDI_CTLOPS_REPORTINT:
709507c3241Smlf case DDI_CTLOPS_REGSIZE:
710507c3241Smlf case DDI_CTLOPS_NREGS:
711507c3241Smlf case DDI_CTLOPS_SLAVEONLY:
712507c3241Smlf case DDI_CTLOPS_AFFINITY:
713507c3241Smlf case DDI_CTLOPS_POKE:
714507c3241Smlf case DDI_CTLOPS_PEEK:
715507c3241Smlf
716507c3241Smlf /* These ops shouldn't be called by a target driver */
717507c3241Smlf ADBG_ERROR(("ata_bus_ctl: %s%d: invalid op (%d) from %s%d\n",
7182df1fe9cSrandyf ddi_driver_name(d), ddi_get_instance(d), o,
7192df1fe9cSrandyf ddi_driver_name(r), ddi_get_instance(r)));
720507c3241Smlf
721507c3241Smlf return (DDI_FAILURE);
722507c3241Smlf
723507c3241Smlf case DDI_CTLOPS_REPORTDEV:
724507c3241Smlf case DDI_CTLOPS_INITCHILD:
725507c3241Smlf case DDI_CTLOPS_UNINITCHILD:
726507c3241Smlf
727507c3241Smlf /* these require special handling below */
728507c3241Smlf break;
729507c3241Smlf
730507c3241Smlf default:
731507c3241Smlf return (ddi_ctlops(d, r, o, a, v));
732507c3241Smlf }
733507c3241Smlf
734507c3241Smlf /* get targets dip */
735507c3241Smlf
736507c3241Smlf if (o == DDI_CTLOPS_INITCHILD || o == DDI_CTLOPS_UNINITCHILD)
737507c3241Smlf tdip = (dev_info_t *)a;
738507c3241Smlf else
739507c3241Smlf tdip = r;
740507c3241Smlf
741507c3241Smlf /*
742507c3241Smlf * XXX - Get class of target
743507c3241Smlf * Before the "class" entry in a conf file becomes
744507c3241Smlf * a real property, we use an additional property
745507c3241Smlf * tentatively called "class_prop". We will require that
746507c3241Smlf * new classes (ie. direct) export "class_prop".
747507c3241Smlf * SCSA target drivers will not have this property, so
748507c3241Smlf * no property implies SCSA.
749507c3241Smlf */
750507c3241Smlf if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, tdip, DDI_PROP_DONTPASS,
751507c3241Smlf "class", &bufp) == DDI_PROP_SUCCESS) ||
752507c3241Smlf (ddi_prop_lookup_string(DDI_DEV_T_ANY, tdip, DDI_PROP_DONTPASS,
753507c3241Smlf "class_prop", &bufp) == DDI_PROP_SUCCESS)) {
754507c3241Smlf if (strcmp(bufp, "dada") == 0)
755507c3241Smlf target_type = ATA_DEV_DISK;
756507c3241Smlf else if (strcmp(bufp, "scsi") == 0)
757507c3241Smlf target_type = ATA_DEV_ATAPI;
758507c3241Smlf else {
759507c3241Smlf ADBG_WARN(("ata_bus_ctl: invalid target class %s\n",
7602df1fe9cSrandyf bufp));
761507c3241Smlf ddi_prop_free(bufp);
762507c3241Smlf return (DDI_FAILURE);
763507c3241Smlf }
764507c3241Smlf ddi_prop_free(bufp);
765507c3241Smlf } else {
766507c3241Smlf target_type = ATA_DEV_ATAPI; /* no class prop, assume SCSI */
767507c3241Smlf }
768507c3241Smlf
769507c3241Smlf if (o == DDI_CTLOPS_INITCHILD) {
770507c3241Smlf int instance = ddi_get_instance(d);
771507c3241Smlf ata_ctl_t *ata_ctlp = ddi_get_soft_state(ata_state, instance);
772507c3241Smlf ata_drv_t *ata_drvp;
773507c3241Smlf int targ;
774507c3241Smlf int lun;
775507c3241Smlf int drive_type;
776507c3241Smlf char *disk_prop;
777507c3241Smlf char *class_prop;
778507c3241Smlf
779507c3241Smlf if (ata_ctlp == NULL) {
780507c3241Smlf ADBG_WARN(("ata_bus_ctl: failed to find ctl struct\n"));
781507c3241Smlf return (DDI_FAILURE);
782507c3241Smlf }
783507c3241Smlf
784507c3241Smlf /* get (target,lun) of child device */
785507c3241Smlf
786507c3241Smlf targ = ddi_prop_get_int(DDI_DEV_T_ANY, tdip, DDI_PROP_DONTPASS,
7872df1fe9cSrandyf "target", -1);
788507c3241Smlf if (targ == -1) {
789507c3241Smlf ADBG_WARN(("ata_bus_ctl: failed to get targ num\n"));
790507c3241Smlf return (DDI_FAILURE);
791507c3241Smlf }
792507c3241Smlf
793507c3241Smlf lun = ddi_prop_get_int(DDI_DEV_T_ANY, tdip, DDI_PROP_DONTPASS,
7942df1fe9cSrandyf "lun", 0);
795507c3241Smlf
796507c3241Smlf if ((targ < 0) || (targ >= ATA_MAXTARG) ||
7972df1fe9cSrandyf (lun < 0) || (lun >= ATA_MAXLUN)) {
798507c3241Smlf return (DDI_FAILURE);
799507c3241Smlf }
800507c3241Smlf
801507c3241Smlf ata_drvp = CTL2DRV(ata_ctlp, targ, lun);
802507c3241Smlf
803507c3241Smlf if (ata_drvp == NULL)
804507c3241Smlf return (DDI_FAILURE); /* no drive */
805507c3241Smlf
806507c3241Smlf /* get type of device */
807507c3241Smlf
808507c3241Smlf if (ATAPIDRV(ata_drvp))
809507c3241Smlf drive_type = ATA_DEV_ATAPI;
810507c3241Smlf else
811507c3241Smlf drive_type = ATA_DEV_DISK;
812507c3241Smlf
813507c3241Smlf /*
814507c3241Smlf * Check for special handling when child driver is
815507c3241Smlf * cmdk (which morphs to the correct interface)
816507c3241Smlf */
817507c3241Smlf if (strcmp(ddi_get_name(tdip), "cmdk") == 0) {
818507c3241Smlf
819507c3241Smlf if ((target_type == ATA_DEV_DISK) &&
8202df1fe9cSrandyf (target_type != drive_type))
821507c3241Smlf return (DDI_FAILURE);
822507c3241Smlf
823507c3241Smlf target_type = drive_type;
824507c3241Smlf
825507c3241Smlf if (drive_type == ATA_DEV_ATAPI) {
826507c3241Smlf class_prop = "scsi";
827507c3241Smlf } else {
828507c3241Smlf disk_prop = "dadk";
829507c3241Smlf class_prop = "dada";
830507c3241Smlf
831507c3241Smlf if (ndi_prop_update_string(DDI_DEV_T_NONE, tdip,
832507c3241Smlf "disk", disk_prop) != DDI_PROP_SUCCESS) {
833507c3241Smlf ADBG_WARN(("ata_bus_ctl: failed to "
8342df1fe9cSrandyf "create disk prop\n"));
835507c3241Smlf return (DDI_FAILURE);
8362df1fe9cSrandyf }
837507c3241Smlf }
838507c3241Smlf
839507c3241Smlf if (ndi_prop_update_string(DDI_DEV_T_NONE, tdip,
840507c3241Smlf "class_prop", class_prop) != DDI_PROP_SUCCESS) {
841507c3241Smlf ADBG_WARN(("ata_bus_ctl: failed to "
842507c3241Smlf "create class prop\n"));
843507c3241Smlf return (DDI_FAILURE);
844507c3241Smlf }
845507c3241Smlf }
846507c3241Smlf
847507c3241Smlf /* Check that target class matches the device */
848507c3241Smlf
849507c3241Smlf if (target_type != drive_type)
850507c3241Smlf return (DDI_FAILURE);
851507c3241Smlf
852507c3241Smlf /* save pointer to drive struct for ata_disk_bus_ctl */
853507c3241Smlf ddi_set_driver_private(tdip, ata_drvp);
854507c3241Smlf
855507c3241Smlf /*
856507c3241Smlf * Determine whether to enable DMA support for this drive. This
857507c3241Smlf * check is deferred to this point so that the various dma
858507c3241Smlf * properties could reside on the devinfo node should finer
859507c3241Smlf * grained dma control be required.
860507c3241Smlf */
8615fb86baeSml if (ata_drvp->ad_pciide_dma == ATA_DMA_UNINITIALIZED) {
8625fb86baeSml ata_drvp->ad_pciide_dma =
8635fb86baeSml ata_init_drive_pcidma(ata_ctlp, ata_drvp, tdip);
8645fb86baeSml ata_show_transfer_mode(ata_ctlp, ata_drvp);
8655fb86baeSml }
866507c3241Smlf }
867507c3241Smlf
868507c3241Smlf if (target_type == ATA_DEV_ATAPI) {
869507c3241Smlf rc = scsa_bus_ops_p->bus_ctl(d, r, o, a, v);
870507c3241Smlf } else {
871507c3241Smlf rc = ata_disk_bus_ctl(d, r, o, a, v);
872507c3241Smlf }
873507c3241Smlf
874507c3241Smlf return (rc);
875507c3241Smlf }
876507c3241Smlf
877507c3241Smlf /*
878507c3241Smlf *
879507c3241Smlf * GHD ccc_hba_complete callback
880507c3241Smlf *
881507c3241Smlf */
882507c3241Smlf
883507c3241Smlf /* ARGSUSED */
884507c3241Smlf static void
ata_hba_complete(void * hba_handle,gcmd_t * gcmdp,int do_callback)885507c3241Smlf ata_hba_complete(
886507c3241Smlf void *hba_handle,
887507c3241Smlf gcmd_t *gcmdp,
888507c3241Smlf int do_callback)
889507c3241Smlf {
890507c3241Smlf ata_drv_t *ata_drvp;
891507c3241Smlf ata_pkt_t *ata_pktp;
892507c3241Smlf
893507c3241Smlf ADBG_TRACE(("ata_hba_complete entered\n"));
894507c3241Smlf
895507c3241Smlf ata_drvp = GCMD2DRV(gcmdp);
896507c3241Smlf ata_pktp = GCMD2APKT(gcmdp);
897507c3241Smlf if (ata_pktp->ap_complete)
898507c3241Smlf (*ata_pktp->ap_complete)(ata_drvp, ata_pktp,
8992df1fe9cSrandyf do_callback);
900507c3241Smlf }
901507c3241Smlf
902507c3241Smlf /* GHD ccc_timeout_func callback */
903507c3241Smlf
904507c3241Smlf /* ARGSUSED */
905507c3241Smlf static int
ata_timeout_func(void * hba_handle,gcmd_t * gcmdp,gtgt_t * gtgtp,gact_t action,int calltype)906507c3241Smlf ata_timeout_func(
907507c3241Smlf void *hba_handle,
908507c3241Smlf gcmd_t *gcmdp,
909507c3241Smlf gtgt_t *gtgtp,
910507c3241Smlf gact_t action,
911507c3241Smlf int calltype)
912507c3241Smlf {
913507c3241Smlf ata_ctl_t *ata_ctlp;
914507c3241Smlf ata_pkt_t *ata_pktp;
9155fb86baeSml ata_drv_t *ata_drvp;
916507c3241Smlf
917507c3241Smlf ADBG_TRACE(("ata_timeout_func entered\n"));
918507c3241Smlf
919507c3241Smlf ata_ctlp = (ata_ctl_t *)hba_handle;
920507c3241Smlf
921507c3241Smlf if (gcmdp != NULL)
922507c3241Smlf ata_pktp = GCMD2APKT(gcmdp);
923507c3241Smlf else
924507c3241Smlf ata_pktp = NULL;
925507c3241Smlf
926507c3241Smlf switch (action) {
927507c3241Smlf case GACTION_EARLY_ABORT:
928507c3241Smlf /* abort before request was started */
929507c3241Smlf if (ata_pktp != NULL) {
930507c3241Smlf ata_pktp->ap_flags |= AP_ABORT;
931507c3241Smlf }
932507c3241Smlf ghd_complete(&ata_ctlp->ac_ccc, gcmdp);
933507c3241Smlf return (TRUE);
934507c3241Smlf
935507c3241Smlf case GACTION_EARLY_TIMEOUT:
936507c3241Smlf /* timeout before request was started */
937507c3241Smlf if (ata_pktp != NULL) {
938507c3241Smlf ata_pktp->ap_flags |= AP_TIMEOUT;
939507c3241Smlf }
940507c3241Smlf ghd_complete(&ata_ctlp->ac_ccc, gcmdp);
941507c3241Smlf return (TRUE);
942507c3241Smlf
943507c3241Smlf case GACTION_RESET_TARGET:
944507c3241Smlf /*
945507c3241Smlf * Reset a device is not supported. Resetting a specific
946507c3241Smlf * device can't be done at all to an ATA device and if
947507c3241Smlf * you send a RESET to an ATAPI device you have to
948507c3241Smlf * reset the whole bus to make certain both devices
949507c3241Smlf * on the bus stay in sync regarding which device is
950507c3241Smlf * the currently selected one.
951507c3241Smlf */
952507c3241Smlf return (FALSE);
953507c3241Smlf
954507c3241Smlf case GACTION_RESET_BUS:
955507c3241Smlf /*
956507c3241Smlf * Issue bus reset and reinitialize both drives.
957507c3241Smlf * But only if this is a timed-out request. Target
958507c3241Smlf * driver reset requests are ignored because ATA
959507c3241Smlf * and ATAPI devices shouldn't be gratuitously reset.
9605fb86baeSml * Also disable DMA if it is a CF device.
961507c3241Smlf */
962507c3241Smlf if (gcmdp == NULL)
963507c3241Smlf break;
9645fb86baeSml ata_drvp = GCMD2DRV(gcmdp);
9655fb86baeSml if (ata_drvp != NULL)
9665fb86baeSml if (ata_drvp->ad_id.ai_config == ATA_ID_CF_TO_ATA)
9675fb86baeSml ata_disable_DMA(ata_drvp);
968507c3241Smlf return (ata_reset_bus(ata_ctlp));
969507c3241Smlf default:
970507c3241Smlf break;
971507c3241Smlf }
972507c3241Smlf return (FALSE);
973507c3241Smlf }
974507c3241Smlf
975507c3241Smlf /*
976507c3241Smlf *
977507c3241Smlf * Initialize controller's soft-state structure
978507c3241Smlf *
979507c3241Smlf */
980507c3241Smlf
981507c3241Smlf static ata_ctl_t *
ata_init_controller(dev_info_t * dip)982507c3241Smlf ata_init_controller(
983507c3241Smlf dev_info_t *dip)
984507c3241Smlf {
985507c3241Smlf ata_ctl_t *ata_ctlp;
986507c3241Smlf int instance;
987507c3241Smlf caddr_t ioaddr1;
988507c3241Smlf caddr_t ioaddr2;
989507c3241Smlf
990507c3241Smlf ADBG_TRACE(("ata_init_controller entered\n"));
991507c3241Smlf
992507c3241Smlf instance = ddi_get_instance(dip);
993507c3241Smlf
994507c3241Smlf /* allocate controller structure */
995507c3241Smlf if (ddi_soft_state_zalloc(ata_state, instance) != DDI_SUCCESS) {
996507c3241Smlf ADBG_WARN(("ata_init_controller: soft_state_zalloc failed\n"));
997507c3241Smlf return (NULL);
998507c3241Smlf }
999507c3241Smlf
1000507c3241Smlf ata_ctlp = ddi_get_soft_state(ata_state, instance);
1001507c3241Smlf
1002507c3241Smlf if (ata_ctlp == NULL) {
1003507c3241Smlf ADBG_WARN(("ata_init_controller: failed to find "
10042df1fe9cSrandyf "controller struct\n"));
1005507c3241Smlf return (NULL);
1006507c3241Smlf }
1007507c3241Smlf
1008507c3241Smlf /*
1009507c3241Smlf * initialize per-controller data
1010507c3241Smlf */
1011507c3241Smlf ata_ctlp->ac_dip = dip;
1012507c3241Smlf ata_ctlp->ac_arq_pktp = kmem_zalloc(sizeof (ata_pkt_t), KM_SLEEP);
1013507c3241Smlf
1014507c3241Smlf /*
1015507c3241Smlf * map the device registers
1016507c3241Smlf */
1017507c3241Smlf if (!ata_setup_ioaddr(dip, &ata_ctlp->ac_iohandle1, &ioaddr1,
10182df1fe9cSrandyf &ata_ctlp->ac_iohandle2, &ioaddr2,
10192df1fe9cSrandyf &ata_ctlp->ac_bmhandle, &ata_ctlp->ac_bmaddr)) {
1020507c3241Smlf (void) ata_detach(dip, DDI_DETACH);
1021507c3241Smlf return (NULL);
1022507c3241Smlf }
1023507c3241Smlf
1024507c3241Smlf ADBG_INIT(("ata_init_controller: ioaddr1 = 0x%p, ioaddr2 = 0x%p\n",
10252df1fe9cSrandyf ioaddr1, ioaddr2));
1026507c3241Smlf
1027507c3241Smlf /*
1028507c3241Smlf * Do ARQ setup
1029507c3241Smlf */
1030507c3241Smlf atapi_init_arq(ata_ctlp);
1031507c3241Smlf
1032507c3241Smlf /*
1033507c3241Smlf * Do PCI-IDE setup
1034507c3241Smlf */
1035507c3241Smlf ata_init_pciide(dip, ata_ctlp);
1036507c3241Smlf
1037507c3241Smlf /*
1038507c3241Smlf * port addresses associated with ioaddr1
1039507c3241Smlf */
1040507c3241Smlf ata_ctlp->ac_ioaddr1 = ioaddr1;
1041507c3241Smlf ata_ctlp->ac_data = (ushort_t *)ioaddr1 + AT_DATA;
1042507c3241Smlf ata_ctlp->ac_error = (uchar_t *)ioaddr1 + AT_ERROR;
1043507c3241Smlf ata_ctlp->ac_feature = (uchar_t *)ioaddr1 + AT_FEATURE;
1044507c3241Smlf ata_ctlp->ac_count = (uchar_t *)ioaddr1 + AT_COUNT;
1045507c3241Smlf ata_ctlp->ac_sect = (uchar_t *)ioaddr1 + AT_SECT;
1046507c3241Smlf ata_ctlp->ac_lcyl = (uchar_t *)ioaddr1 + AT_LCYL;
1047507c3241Smlf ata_ctlp->ac_hcyl = (uchar_t *)ioaddr1 + AT_HCYL;
1048507c3241Smlf ata_ctlp->ac_drvhd = (uchar_t *)ioaddr1 + AT_DRVHD;
1049507c3241Smlf ata_ctlp->ac_status = (uchar_t *)ioaddr1 + AT_STATUS;
1050507c3241Smlf ata_ctlp->ac_cmd = (uchar_t *)ioaddr1 + AT_CMD;
1051507c3241Smlf
1052507c3241Smlf /*
1053507c3241Smlf * port addresses associated with ioaddr2
1054507c3241Smlf */
1055507c3241Smlf ata_ctlp->ac_ioaddr2 = ioaddr2;
1056507c3241Smlf ata_ctlp->ac_altstatus = (uchar_t *)ioaddr2 + AT_ALTSTATUS;
1057507c3241Smlf ata_ctlp->ac_devctl = (uchar_t *)ioaddr2 + AT_DEVCTL;
1058507c3241Smlf
1059507c3241Smlf /*
1060507c3241Smlf * If AC_BSY_WAIT needs to be set for laptops that do
1061507c3241Smlf * suspend/resume but do not correctly wait for the busy bit to
1062507c3241Smlf * drop after a resume.
1063507c3241Smlf */
1064507c3241Smlf ata_ctlp->ac_timing_flags = ddi_prop_get_int(DDI_DEV_T_ANY,
10652df1fe9cSrandyf dip, DDI_PROP_DONTPASS, "timing_flags", 0);
1066507c3241Smlf /*
1067507c3241Smlf * get max transfer size, default to 256 sectors
1068507c3241Smlf */
1069507c3241Smlf ata_ctlp->ac_max_transfer = ddi_prop_get_int(DDI_DEV_T_ANY,
10702df1fe9cSrandyf dip, DDI_PROP_DONTPASS, "max_transfer", 0x100);
1071507c3241Smlf if (ata_ctlp->ac_max_transfer < 1)
1072507c3241Smlf ata_ctlp->ac_max_transfer = 1;
1073507c3241Smlf if (ata_ctlp->ac_max_transfer > 0x100)
1074507c3241Smlf ata_ctlp->ac_max_transfer = 0x100;
1075507c3241Smlf
1076507c3241Smlf /*
1077507c3241Smlf * Get the standby timer value
1078507c3241Smlf */
1079507c3241Smlf ata_ctlp->ac_standby_time = ddi_prop_get_int(DDI_DEV_T_ANY,
10802df1fe9cSrandyf dip, DDI_PROP_DONTPASS, "standby", -1);
1081507c3241Smlf
1082507c3241Smlf /*
1083507c3241Smlf * If this is a /pci/pci-ide instance check to see if
1084507c3241Smlf * it's supposed to be attached as an /isa/ata
1085507c3241Smlf */
1086507c3241Smlf if (ata_ctlp->ac_pciide) {
1087507c3241Smlf static char prop_buf[] = "SUNW-ata-ffff-isa";
1088507c3241Smlf int addr1 = (intptr_t)ioaddr1;
1089507c3241Smlf
1090507c3241Smlf
1091507c3241Smlf if (addr1 < 0 || addr1 > 0xffff) {
1092507c3241Smlf (void) ata_detach(dip, DDI_DETACH);
1093507c3241Smlf return (NULL);
1094507c3241Smlf }
1095507c3241Smlf (void) sprintf(prop_buf, "SUNW-ata-%04x-isa",
10962df1fe9cSrandyf addr1);
1097507c3241Smlf if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_root_node(),
10982df1fe9cSrandyf DDI_PROP_DONTPASS, prop_buf)) {
1099507c3241Smlf (void) ata_detach(dip, DDI_DETACH);
1100507c3241Smlf return (NULL);
1101507c3241Smlf }
1102507c3241Smlf }
1103507c3241Smlf
1104507c3241Smlf /* Init controller specific stuff */
1105507c3241Smlf (void) ata_spec_init_controller(dip);
1106507c3241Smlf
1107507c3241Smlf /*
1108507c3241Smlf * initialize GHD
1109507c3241Smlf */
1110507c3241Smlf
1111507c3241Smlf GHD_WAITQ_INIT(&ata_ctlp->ac_ccc.ccc_waitq, NULL, 1);
1112507c3241Smlf
1113507c3241Smlf if (!ghd_register("ata", &ata_ctlp->ac_ccc, dip, 0, ata_ctlp,
11142df1fe9cSrandyf atapi_ccballoc, atapi_ccbfree,
11152df1fe9cSrandyf ata_pciide_dma_sg_func, ata_hba_start,
11162df1fe9cSrandyf ata_hba_complete, ata_intr,
11172df1fe9cSrandyf ata_get_status, ata_process_intr, ata_timeout_func,
11182df1fe9cSrandyf &ata_timer_conf, NULL)) {
1119507c3241Smlf (void) ata_detach(dip, DDI_DETACH);
1120507c3241Smlf return (NULL);
1121507c3241Smlf }
1122507c3241Smlf
1123507c3241Smlf ata_ctlp->ac_flags |= AC_GHD_INIT;
1124507c3241Smlf return (ata_ctlp);
1125507c3241Smlf }
1126507c3241Smlf
1127507c3241Smlf /* destroy a controller */
1128507c3241Smlf
1129507c3241Smlf static void
ata_destroy_controller(dev_info_t * dip)1130507c3241Smlf ata_destroy_controller(
1131507c3241Smlf dev_info_t *dip)
1132507c3241Smlf {
1133507c3241Smlf ata_ctl_t *ata_ctlp;
1134507c3241Smlf int instance;
1135507c3241Smlf
1136507c3241Smlf ADBG_TRACE(("ata_destroy_controller entered\n"));
1137507c3241Smlf
1138507c3241Smlf instance = ddi_get_instance(dip);
1139507c3241Smlf ata_ctlp = ddi_get_soft_state(ata_state, instance);
1140507c3241Smlf
1141507c3241Smlf if (ata_ctlp == NULL)
1142507c3241Smlf return;
1143507c3241Smlf
1144507c3241Smlf /* destroy ghd */
1145507c3241Smlf if (ata_ctlp->ac_flags & AC_GHD_INIT)
1146507c3241Smlf ghd_unregister(&ata_ctlp->ac_ccc);
1147507c3241Smlf
1148507c3241Smlf /* free the pciide buffer (if any) */
1149507c3241Smlf ata_pciide_free(ata_ctlp);
1150507c3241Smlf
1151507c3241Smlf /* destroy controller struct */
1152507c3241Smlf kmem_free(ata_ctlp->ac_arq_pktp, sizeof (ata_pkt_t));
1153507c3241Smlf ddi_soft_state_free(ata_state, instance);
1154507c3241Smlf
1155507c3241Smlf }
1156507c3241Smlf
1157507c3241Smlf
1158507c3241Smlf /*
1159507c3241Smlf *
1160507c3241Smlf * initialize a drive
1161507c3241Smlf *
1162507c3241Smlf */
1163507c3241Smlf
1164507c3241Smlf static ata_drv_t *
ata_init_drive(ata_ctl_t * ata_ctlp,uchar_t targ,uchar_t lun)1165507c3241Smlf ata_init_drive(
1166507c3241Smlf ata_ctl_t *ata_ctlp,
1167507c3241Smlf uchar_t targ,
1168507c3241Smlf uchar_t lun)
1169507c3241Smlf {
1170507c3241Smlf static char nec_260[] = "NEC CD-ROM DRIVE";
1171507c3241Smlf ata_drv_t *ata_drvp;
1172507c3241Smlf struct ata_id *aidp;
1173507c3241Smlf char buf[80];
1174507c3241Smlf int drive_type;
1175507c3241Smlf int i;
1176507c3241Smlf int valid_version = 0;
1177507c3241Smlf
1178507c3241Smlf ADBG_TRACE(("ata_init_drive entered, targ = %d, lun = %d\n",
11792df1fe9cSrandyf targ, lun));
1180507c3241Smlf
1181507c3241Smlf /* check if device already exists */
1182507c3241Smlf
1183507c3241Smlf ata_drvp = CTL2DRV(ata_ctlp, targ, lun);
1184507c3241Smlf
1185507c3241Smlf if (ata_drvp != NULL)
1186507c3241Smlf return (ata_drvp);
1187507c3241Smlf
1188507c3241Smlf /* allocate new device structure */
1189507c3241Smlf
1190507c3241Smlf ata_drvp = kmem_zalloc(sizeof (ata_drv_t), KM_SLEEP);
1191507c3241Smlf aidp = &ata_drvp->ad_id;
1192507c3241Smlf
1193507c3241Smlf /*
1194507c3241Smlf * set up drive struct
1195507c3241Smlf */
1196507c3241Smlf ata_drvp->ad_ctlp = ata_ctlp;
11975fb86baeSml ata_drvp->ad_pciide_dma = ATA_DMA_UNINITIALIZED;
1198507c3241Smlf ata_drvp->ad_targ = targ;
1199507c3241Smlf ata_drvp->ad_drive_bits =
12002df1fe9cSrandyf (ata_drvp->ad_targ == 0 ? ATDH_DRIVE0 : ATDH_DRIVE1);
1201507c3241Smlf /*
1202507c3241Smlf * Add the LUN for SFF-8070i support
1203507c3241Smlf */
1204507c3241Smlf ata_drvp->ad_lun = lun;
1205507c3241Smlf ata_drvp->ad_drive_bits |= ata_drvp->ad_lun;
1206507c3241Smlf
1207507c3241Smlf /*
1208507c3241Smlf * get drive type, side effect is to collect
1209507c3241Smlf * IDENTIFY DRIVE data
1210507c3241Smlf */
1211507c3241Smlf
1212507c3241Smlf drive_type = ata_drive_type(ata_drvp->ad_drive_bits,
12132df1fe9cSrandyf ata_ctlp->ac_iohandle1,
12142df1fe9cSrandyf ata_ctlp->ac_ioaddr1,
12152df1fe9cSrandyf ata_ctlp->ac_iohandle2,
12162df1fe9cSrandyf ata_ctlp->ac_ioaddr2,
12172df1fe9cSrandyf aidp);
1218507c3241Smlf
1219507c3241Smlf switch (drive_type) {
1220507c3241Smlf case ATA_DEV_NONE:
1221507c3241Smlf /* no drive found */
1222507c3241Smlf goto errout;
1223507c3241Smlf case ATA_DEV_ATAPI:
1224507c3241Smlf ata_drvp->ad_flags |= AD_ATAPI;
1225507c3241Smlf break;
1226507c3241Smlf case ATA_DEV_DISK:
1227507c3241Smlf ata_drvp->ad_flags |= AD_DISK;
1228507c3241Smlf break;
1229507c3241Smlf }
1230507c3241Smlf
1231507c3241Smlf /*
1232507c3241Smlf * swap bytes of all text fields
1233507c3241Smlf */
1234507c3241Smlf if (!ata_strncmp(nec_260, aidp->ai_model, sizeof (aidp->ai_model))) {
1235507c3241Smlf swab(aidp->ai_drvser, aidp->ai_drvser,
12362df1fe9cSrandyf sizeof (aidp->ai_drvser));
1237507c3241Smlf swab(aidp->ai_fw, aidp->ai_fw,
12382df1fe9cSrandyf sizeof (aidp->ai_fw));
1239507c3241Smlf swab(aidp->ai_model, aidp->ai_model,
12402df1fe9cSrandyf sizeof (aidp->ai_model));
1241507c3241Smlf }
1242507c3241Smlf
1243507c3241Smlf /*
1244507c3241Smlf * Check if this drive has the Single Sector bug
1245507c3241Smlf */
1246507c3241Smlf
1247507c3241Smlf if (ata_check_drive_blacklist(&ata_drvp->ad_id, ATA_BL_1SECTOR))
1248507c3241Smlf ata_drvp->ad_flags |= AD_1SECTOR;
1249507c3241Smlf else
1250507c3241Smlf ata_drvp->ad_flags &= ~AD_1SECTOR;
1251507c3241Smlf
12528c112d45SColin Yi if (ata_check_drive_blacklist(&ata_drvp->ad_id, ATA_BL_LBA48))
12538c112d45SColin Yi ata_drvp->ad_flags |= AD_BLLBA48;
12548c112d45SColin Yi else
12558c112d45SColin Yi ata_drvp->ad_flags &= ~AD_BLLBA48;
12568c112d45SColin Yi
1257507c3241Smlf /* Check if this drive has the "revert to defaults" bug */
1258507c3241Smlf if (!ata_check_revert_to_defaults(ata_drvp))
1259507c3241Smlf ata_drvp->ad_flags |= AD_NORVRT;
1260507c3241Smlf
1261507c3241Smlf /* Dump the drive info */
1262507c3241Smlf (void) strncpy(buf, aidp->ai_model, sizeof (aidp->ai_model));
1263507c3241Smlf buf[sizeof (aidp->ai_model)-1] = '\0';
1264507c3241Smlf for (i = sizeof (aidp->ai_model) - 2; buf[i] == ' '; i--)
1265507c3241Smlf buf[i] = '\0';
1266507c3241Smlf
1267507c3241Smlf ATAPRT(("?\t%s device at targ %d, lun %d lastlun 0x%x\n",
12682df1fe9cSrandyf (ATAPIDRV(ata_drvp) ? "ATAPI":"IDE"),
12692df1fe9cSrandyf ata_drvp->ad_targ, ata_drvp->ad_lun, aidp->ai_lastlun));
1270507c3241Smlf
1271507c3241Smlf ATAPRT(("?\tmodel %s\n", buf));
1272507c3241Smlf
1273507c3241Smlf if (aidp->ai_majorversion != 0 && aidp->ai_majorversion != 0xffff) {
1274507c3241Smlf for (i = 14; i >= 2; i--) {
1275507c3241Smlf if (aidp->ai_majorversion & (1 << i)) {
1276507c3241Smlf valid_version = i;
1277507c3241Smlf break;
1278507c3241Smlf }
1279507c3241Smlf }
1280507c3241Smlf ATAPRT((
1281507c3241Smlf "?\tATA/ATAPI-%d supported, majver 0x%x minver 0x%x\n",
12822df1fe9cSrandyf valid_version,
12832df1fe9cSrandyf aidp->ai_majorversion,
12842df1fe9cSrandyf aidp->ai_minorversion));
1285507c3241Smlf }
1286507c3241Smlf
1287507c3241Smlf if (ata_capability_data) {
1288507c3241Smlf
1289507c3241Smlf ATAPRT(("?\t\tstat %x, err %x\n",
12902df1fe9cSrandyf ddi_get8(ata_ctlp->ac_iohandle2,
12912df1fe9cSrandyf ata_ctlp->ac_altstatus),
12922df1fe9cSrandyf ddi_get8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_error)));
1293507c3241Smlf
1294507c3241Smlf ATAPRT(("?\t\tcfg 0x%x, cap 0x%x\n",
12952df1fe9cSrandyf aidp->ai_config,
12962df1fe9cSrandyf aidp->ai_cap));
1297507c3241Smlf
1298507c3241Smlf /*
1299507c3241Smlf * Be aware that ATA-6 and later drives may not provide valid
1300507c3241Smlf * geometry information and other obsoleted info.
1301507c3241Smlf * Select what is printed based on supported ATA model (skip
1302507c3241Smlf * anything below ATA/ATAPI-3)
1303507c3241Smlf */
1304507c3241Smlf
1305507c3241Smlf if (valid_version == 0 || aidp->ai_majorversion <
1306507c3241Smlf ATAC_MAJVER_6) {
1307507c3241Smlf /*
1308507c3241Smlf * Supported version less then ATA-6
1309507c3241Smlf */
1310507c3241Smlf ATAPRT(("?\t\tcyl %d, hd %d, sec/trk %d\n",
13112df1fe9cSrandyf aidp->ai_fixcyls,
13122df1fe9cSrandyf aidp->ai_heads,
13132df1fe9cSrandyf aidp->ai_sectors));
1314507c3241Smlf }
1315507c3241Smlf ATAPRT(("?\t\tmult1 0x%x, mult2 0x%x\n",
13162df1fe9cSrandyf aidp->ai_mult1,
13172df1fe9cSrandyf aidp->ai_mult2));
1318507c3241Smlf if (valid_version && aidp->ai_majorversion < ATAC_MAJVER_4) {
1319507c3241Smlf ATAPRT((
1320507c3241Smlf "?\t\tpiomode 0x%x, dmamode 0x%x, advpiomode 0x%x\n",
13212df1fe9cSrandyf aidp->ai_piomode,
13222df1fe9cSrandyf aidp->ai_dmamode,
13232df1fe9cSrandyf aidp->ai_advpiomode));
1324507c3241Smlf } else {
1325507c3241Smlf ATAPRT(("?\t\tadvpiomode 0x%x\n",
13262df1fe9cSrandyf aidp->ai_advpiomode));
1327507c3241Smlf }
1328507c3241Smlf ATAPRT(("?\t\tminpio %d, minpioflow %d\n",
13292df1fe9cSrandyf aidp->ai_minpio,
13302df1fe9cSrandyf aidp->ai_minpioflow));
1331507c3241Smlf if (valid_version && aidp->ai_majorversion >= ATAC_MAJVER_4 &&
1332507c3241Smlf (aidp->ai_validinfo & ATAC_VALIDINFO_83)) {
1333507c3241Smlf ATAPRT(("?\t\tdwdma 0x%x, ultradma 0x%x\n",
13342df1fe9cSrandyf aidp->ai_dworddma,
13352df1fe9cSrandyf aidp->ai_ultradma));
1336507c3241Smlf } else {
1337507c3241Smlf ATAPRT(("?\t\tdwdma 0x%x\n",
13382df1fe9cSrandyf aidp->ai_dworddma));
1339507c3241Smlf }
1340507c3241Smlf }
1341507c3241Smlf
1342507c3241Smlf if (ATAPIDRV(ata_drvp)) {
1343507c3241Smlf if (!atapi_init_drive(ata_drvp))
1344507c3241Smlf goto errout;
1345507c3241Smlf } else {
1346507c3241Smlf if (!ata_disk_init_drive(ata_drvp))
1347507c3241Smlf goto errout;
1348507c3241Smlf }
1349507c3241Smlf
1350507c3241Smlf /*
1351507c3241Smlf * store pointer in controller struct
1352507c3241Smlf */
1353507c3241Smlf CTL2DRV(ata_ctlp, targ, lun) = ata_drvp;
1354507c3241Smlf
1355507c3241Smlf /*
1356507c3241Smlf * lock the drive's current settings in case I have to
1357507c3241Smlf * reset the drive due to some sort of error
1358507c3241Smlf */
13592df1fe9cSrandyf (void) ata_set_feature(ata_ctlp, ata_drvp, ATSF_DIS_REVPOD, 0);
1360507c3241Smlf
1361507c3241Smlf return (ata_drvp);
1362507c3241Smlf
1363507c3241Smlf errout:
1364507c3241Smlf ata_uninit_drive(ata_drvp);
1365507c3241Smlf return (NULL);
1366507c3241Smlf }
1367507c3241Smlf
1368507c3241Smlf /* destroy a drive */
1369507c3241Smlf
1370507c3241Smlf static void
ata_uninit_drive(ata_drv_t * ata_drvp)1371507c3241Smlf ata_uninit_drive(
1372507c3241Smlf ata_drv_t *ata_drvp)
1373507c3241Smlf {
1374507c3241Smlf #if 0
1375507c3241Smlf ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
1376507c3241Smlf #endif
1377507c3241Smlf
1378507c3241Smlf ADBG_TRACE(("ata_uninit_drive entered\n"));
1379507c3241Smlf
1380507c3241Smlf #if 0
1381507c3241Smlf /*
1382507c3241Smlf * DON'T DO THIS. disabling interrupts floats the IRQ line
1383507c3241Smlf * which generates spurious interrupts
1384507c3241Smlf */
1385507c3241Smlf
1386507c3241Smlf /*
1387507c3241Smlf * Select the correct drive
1388507c3241Smlf */
1389507c3241Smlf ddi_put8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_drvhd,
13902df1fe9cSrandyf ata_drvp->ad_drive_bits);
13919f49ae27Smlf ata_nsecwait(400);
1392507c3241Smlf
1393507c3241Smlf /*
1394507c3241Smlf * Disable interrupts from the drive
1395507c3241Smlf */
1396507c3241Smlf ddi_put8(ata_ctlp->ac_iohandle2, ata_ctlp->ac_devctl,
13972df1fe9cSrandyf (ATDC_D3 | ATDC_NIEN));
1398507c3241Smlf #endif
1399507c3241Smlf
1400507c3241Smlf /* interface specific clean-ups */
1401507c3241Smlf
1402507c3241Smlf if (ata_drvp->ad_flags & AD_ATAPI)
1403507c3241Smlf atapi_uninit_drive(ata_drvp);
1404507c3241Smlf else if (ata_drvp->ad_flags & AD_DISK)
1405507c3241Smlf ata_disk_uninit_drive(ata_drvp);
1406507c3241Smlf
1407507c3241Smlf /* free drive struct */
1408507c3241Smlf
1409507c3241Smlf kmem_free(ata_drvp, sizeof (ata_drv_t));
1410507c3241Smlf }
1411507c3241Smlf
1412507c3241Smlf
1413507c3241Smlf /*
1414507c3241Smlf * ata_drive_type()
1415507c3241Smlf *
1416507c3241Smlf * The timeout values and exact sequence of checking is critical
1417507c3241Smlf * especially for atapi device detection, and should not be changed lightly.
1418507c3241Smlf *
1419507c3241Smlf */
1420507c3241Smlf static int
ata_drive_type(uchar_t drvhd,ddi_acc_handle_t io_hdl1,caddr_t ioaddr1,ddi_acc_handle_t io_hdl2,caddr_t ioaddr2,struct ata_id * ata_id_bufp)1421507c3241Smlf ata_drive_type(
1422507c3241Smlf uchar_t drvhd,
1423507c3241Smlf ddi_acc_handle_t io_hdl1,
1424507c3241Smlf caddr_t ioaddr1,
1425507c3241Smlf ddi_acc_handle_t io_hdl2,
1426507c3241Smlf caddr_t ioaddr2,
1427507c3241Smlf struct ata_id *ata_id_bufp)
1428507c3241Smlf {
1429507c3241Smlf uchar_t status;
1430507c3241Smlf
1431507c3241Smlf ADBG_TRACE(("ata_drive_type entered\n"));
1432507c3241Smlf
1433507c3241Smlf /*
1434507c3241Smlf * select the appropriate drive and LUN
1435507c3241Smlf */
1436507c3241Smlf ddi_put8(io_hdl1, (uchar_t *)ioaddr1 + AT_DRVHD, drvhd);
14379f49ae27Smlf ata_nsecwait(400);
1438507c3241Smlf
1439507c3241Smlf /*
1440507c3241Smlf * make certain the drive is selected, and wait for not busy
1441507c3241Smlf */
1442507c3241Smlf (void) ata_wait3(io_hdl2, ioaddr2, 0, ATS_BSY, 0x7f, 0, 0x7f, 0,
14432df1fe9cSrandyf 5 * 1000000);
1444507c3241Smlf
1445507c3241Smlf status = ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS);
1446507c3241Smlf
1447b3c0e203Smlf if (status & ATS_BSY) {
14489f49ae27Smlf ADBG_TRACE(("ata_drive_type 0x%p 0x%x\n", ioaddr1, status));
1449507c3241Smlf return (ATA_DEV_NONE);
1450507c3241Smlf }
1451507c3241Smlf
1452507c3241Smlf if (ata_disk_id(io_hdl1, ioaddr1, io_hdl2, ioaddr2, ata_id_bufp))
1453507c3241Smlf return (ATA_DEV_DISK);
1454507c3241Smlf
1455507c3241Smlf /*
1456507c3241Smlf * No disk, check for atapi unit.
1457507c3241Smlf */
1458507c3241Smlf if (!atapi_signature(io_hdl1, ioaddr1)) {
1459507c3241Smlf #ifndef ATA_DISABLE_ATAPI_1_7
1460507c3241Smlf /*
1461507c3241Smlf * Check for old (but prevalent) atapi 1.7B
1462507c3241Smlf * spec device, the only known example is the
1463507c3241Smlf * NEC CDR-260 (not 260R which is (mostly) ATAPI 1.2
1464507c3241Smlf * compliant). This device has no signature
1465507c3241Smlf * and requires conversion from hex to BCD
1466507c3241Smlf * for some scsi audio commands.
1467507c3241Smlf */
1468507c3241Smlf if (atapi_id(io_hdl1, ioaddr1, io_hdl2, ioaddr2, ata_id_bufp)) {
1469507c3241Smlf return (ATA_DEV_ATAPI);
1470507c3241Smlf }
1471507c3241Smlf #endif
1472507c3241Smlf return (ATA_DEV_NONE);
1473507c3241Smlf }
1474507c3241Smlf
1475507c3241Smlf if (atapi_id(io_hdl1, ioaddr1, io_hdl2, ioaddr2, ata_id_bufp)) {
1476507c3241Smlf return (ATA_DEV_ATAPI);
1477507c3241Smlf }
1478507c3241Smlf
1479507c3241Smlf return (ATA_DEV_NONE);
1480507c3241Smlf
1481507c3241Smlf }
1482507c3241Smlf
14839f49ae27Smlf /*
14849f49ae27Smlf * nsec-granularity time delay function
14859f49ae27Smlf */
14869f49ae27Smlf void
ata_nsecwait(clock_t count)14879f49ae27Smlf ata_nsecwait(clock_t count)
14889f49ae27Smlf {
14899f49ae27Smlf extern int tsc_gethrtime_initted;
14909f49ae27Smlf
14919f49ae27Smlf if (tsc_gethrtime_initted) {
14929f49ae27Smlf hrtime_t end = gethrtime() + count;
14939f49ae27Smlf
14949f49ae27Smlf while (gethrtime() < end) {
14959f49ae27Smlf SMT_PAUSE();
14969f49ae27Smlf }
14979f49ae27Smlf } else {
14989f49ae27Smlf drv_usecwait(1 + (count / 1000));
14999f49ae27Smlf }
15009f49ae27Smlf }
15019f49ae27Smlf
15029f49ae27Smlf
1503507c3241Smlf /*
1504507c3241Smlf * Wait for a register of a controller to achieve a specific state.
1505507c3241Smlf * To return normally, all the bits in the first sub-mask must be ON,
1506507c3241Smlf * all the bits in the second sub-mask must be OFF.
1507507c3241Smlf * If timeout_usec microseconds pass without the controller achieving
1508507c3241Smlf * the desired bit configuration, we return TRUE, else FALSE.
1509507c3241Smlf */
1510507c3241Smlf
1511507c3241Smlf int ata_usec_delay = 10;
1512507c3241Smlf
1513507c3241Smlf int
ata_wait(ddi_acc_handle_t io_hdl,caddr_t ioaddr,uchar_t onbits,uchar_t offbits,uint_t timeout_usec)1514507c3241Smlf ata_wait(
1515507c3241Smlf ddi_acc_handle_t io_hdl,
1516507c3241Smlf caddr_t ioaddr,
1517507c3241Smlf uchar_t onbits,
1518507c3241Smlf uchar_t offbits,
1519507c3241Smlf uint_t timeout_usec)
1520507c3241Smlf {
1521507c3241Smlf ushort_t val;
15229f49ae27Smlf hrtime_t deadline = gethrtime() +
15239f49ae27Smlf (hrtime_t)timeout_usec * (NANOSEC / MICROSEC);
15249f49ae27Smlf
1525507c3241Smlf
1526507c3241Smlf do {
1527507c3241Smlf val = ddi_get8(io_hdl, (uchar_t *)ioaddr + AT_ALTSTATUS);
1528507c3241Smlf if ((val & onbits) == onbits && (val & offbits) == 0)
1529507c3241Smlf return (TRUE);
1530507c3241Smlf drv_usecwait(ata_usec_delay);
15319f49ae27Smlf } while (gethrtime() < deadline);
1532507c3241Smlf
1533507c3241Smlf return (FALSE);
1534507c3241Smlf }
1535507c3241Smlf
1536507c3241Smlf
1537507c3241Smlf /*
1538507c3241Smlf *
1539507c3241Smlf * This is a slightly more complicated version that checks
1540507c3241Smlf * for error conditions and bails-out rather than looping
1541507c3241Smlf * until the timeout expires
1542507c3241Smlf */
1543507c3241Smlf int
ata_wait3(ddi_acc_handle_t io_hdl,caddr_t ioaddr,uchar_t onbits1,uchar_t offbits1,uchar_t failure_onbits2,uchar_t failure_offbits2,uchar_t failure_onbits3,uchar_t failure_offbits3,uint_t timeout_usec)1544507c3241Smlf ata_wait3(
1545507c3241Smlf ddi_acc_handle_t io_hdl,
1546507c3241Smlf caddr_t ioaddr,
1547507c3241Smlf uchar_t onbits1,
1548507c3241Smlf uchar_t offbits1,
1549507c3241Smlf uchar_t failure_onbits2,
1550507c3241Smlf uchar_t failure_offbits2,
1551507c3241Smlf uchar_t failure_onbits3,
1552507c3241Smlf uchar_t failure_offbits3,
1553507c3241Smlf uint_t timeout_usec)
1554507c3241Smlf {
1555507c3241Smlf ushort_t val;
15569f49ae27Smlf hrtime_t deadline = gethrtime() +
15579f49ae27Smlf (hrtime_t)timeout_usec * (NANOSEC / MICROSEC);
1558507c3241Smlf
1559507c3241Smlf do {
1560507c3241Smlf val = ddi_get8(io_hdl, (uchar_t *)ioaddr + AT_ALTSTATUS);
1561507c3241Smlf
1562507c3241Smlf /*
1563507c3241Smlf * check for expected condition
1564507c3241Smlf */
1565507c3241Smlf if ((val & onbits1) == onbits1 && (val & offbits1) == 0)
1566507c3241Smlf return (TRUE);
1567507c3241Smlf
1568507c3241Smlf /*
1569507c3241Smlf * check for error conditions
1570507c3241Smlf */
1571507c3241Smlf if ((val & failure_onbits2) == failure_onbits2 &&
15722df1fe9cSrandyf (val & failure_offbits2) == 0) {
1573507c3241Smlf return (FALSE);
1574507c3241Smlf }
1575507c3241Smlf
1576507c3241Smlf if ((val & failure_onbits3) == failure_onbits3 &&
15772df1fe9cSrandyf (val & failure_offbits3) == 0) {
1578507c3241Smlf return (FALSE);
1579507c3241Smlf }
1580507c3241Smlf
1581507c3241Smlf drv_usecwait(ata_usec_delay);
15829f49ae27Smlf } while (gethrtime() < deadline);
1583507c3241Smlf
1584507c3241Smlf return (FALSE);
1585507c3241Smlf }
1586507c3241Smlf
1587507c3241Smlf
1588507c3241Smlf /*
1589507c3241Smlf *
1590507c3241Smlf * low level routine for ata_disk_id() and atapi_id()
1591507c3241Smlf *
1592507c3241Smlf */
1593507c3241Smlf
1594507c3241Smlf int
ata_id_common(uchar_t id_cmd,int expect_drdy,ddi_acc_handle_t io_hdl1,caddr_t ioaddr1,ddi_acc_handle_t io_hdl2,caddr_t ioaddr2,struct ata_id * aidp)1595507c3241Smlf ata_id_common(
1596507c3241Smlf uchar_t id_cmd,
1597507c3241Smlf int expect_drdy,
1598507c3241Smlf ddi_acc_handle_t io_hdl1,
1599507c3241Smlf caddr_t ioaddr1,
1600507c3241Smlf ddi_acc_handle_t io_hdl2,
1601507c3241Smlf caddr_t ioaddr2,
1602507c3241Smlf struct ata_id *aidp)
1603507c3241Smlf {
1604507c3241Smlf uchar_t status;
1605507c3241Smlf
1606507c3241Smlf ADBG_TRACE(("ata_id_common entered\n"));
1607507c3241Smlf
1608507c3241Smlf bzero(aidp, sizeof (struct ata_id));
1609507c3241Smlf
1610507c3241Smlf /*
1611507c3241Smlf * clear the features register
1612507c3241Smlf */
1613507c3241Smlf ddi_put8(io_hdl1, (uchar_t *)ioaddr1 + AT_FEATURE, 0);
1614507c3241Smlf
1615507c3241Smlf /*
1616b3c0e203Smlf * Disable interrupts from the device. When the ata
1617b3c0e203Smlf * hardware is sharing its interrupt with another
1618b3c0e203Smlf * device, the shared interrupt might have already been
1619b3c0e203Smlf * unmasked in the interrupt controller and
16209f49ae27Smlf * triggering ata device interrupts will result in an
16219f49ae27Smlf * interrupt storm and a hung system.
1622507c3241Smlf */
16239f49ae27Smlf ddi_put8(io_hdl2, (uchar_t *)ioaddr2 + AT_DEVCTL, ATDC_D3 | ATDC_NIEN);
1624507c3241Smlf
1625507c3241Smlf /*
1626507c3241Smlf * issue IDENTIFY DEVICE or IDENTIFY PACKET DEVICE command
1627507c3241Smlf */
1628507c3241Smlf ddi_put8(io_hdl1, (uchar_t *)ioaddr1 + AT_CMD, id_cmd);
1629507c3241Smlf
1630507c3241Smlf /* wait for the busy bit to settle */
16319f49ae27Smlf ata_nsecwait(400);
1632507c3241Smlf
1633b3c0e203Smlf /*
1634b3c0e203Smlf * read alternate status and check for conditions which
1635b3c0e203Smlf * may indicate the drive is not present, to prevent getting
1636b3c0e203Smlf * stuck in ata_wait3() below.
1637b3c0e203Smlf */
1638b3c0e203Smlf status = ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS);
1639b3c0e203Smlf
1640b3c0e203Smlf /*
1641b3c0e203Smlf * 0x0, 0x7f, or ATS_DF can happen when no drive is present
1642b3c0e203Smlf */
1643b3c0e203Smlf if ((status == 0x0) || (status == 0x7f) ||
1644b3c0e203Smlf ((status & (ATS_BSY|ATS_DF)) == ATS_DF)) {
1645b3c0e203Smlf /* invalid status, can't be an ATA or ATAPI device */
1646b3c0e203Smlf return (FALSE);
1647b3c0e203Smlf }
1648b3c0e203Smlf
1649507c3241Smlf /*
1650507c3241Smlf * According to the ATA specification, some drives may have
1651507c3241Smlf * to read the media to complete this command. We need to
1652507c3241Smlf * make sure we give them enough time to respond.
1653507c3241Smlf */
1654507c3241Smlf (void) ata_wait3(io_hdl2, ioaddr2, 0, ATS_BSY,
16552df1fe9cSrandyf ATS_ERR, ATS_BSY, 0x7f, 0, 5 * 1000000);
1656507c3241Smlf
1657507c3241Smlf /*
1658507c3241Smlf * read the status byte and clear the pending interrupt
1659507c3241Smlf */
1660b3c0e203Smlf status = ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_STATUS);
1661507c3241Smlf
1662507c3241Smlf /*
1663b3c0e203Smlf * this happens if there's no drive present
1664507c3241Smlf */
1665b3c0e203Smlf if (status == 0xff || status == 0x7f) {
1666507c3241Smlf /* invalid status, can't be an ATA or ATAPI device */
1667507c3241Smlf return (FALSE);
1668507c3241Smlf }
1669507c3241Smlf
1670507c3241Smlf if (status & ATS_BSY) {
1671507c3241Smlf ADBG_ERROR(("ata_id_common: BUSY status 0x%x error 0x%x\n",
16722df1fe9cSrandyf ddi_get8(io_hdl2, (uchar_t *)ioaddr2 +AT_ALTSTATUS),
16732df1fe9cSrandyf ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR)));
1674507c3241Smlf return (FALSE);
1675507c3241Smlf }
1676507c3241Smlf
1677507c3241Smlf if (!(status & ATS_DRQ)) {
1678507c3241Smlf if (status & (ATS_ERR | ATS_DF)) {
1679507c3241Smlf return (FALSE);
1680507c3241Smlf }
1681507c3241Smlf /*
1682507c3241Smlf * Give the drive another second to assert DRQ. Some older
1683ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic * drives de-assert BSY before asserting DRQ. Bail out
1684ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic * immediately if the status becomes 0x7f, which is invalid
1685ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic * value. It can happen when no drive is present.
1686507c3241Smlf */
1687ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic if (!ata_wait3(io_hdl2, ioaddr2, ATS_DRQ, ATS_BSY, 0x7f,
1688ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic ATS_BSY, 0x7f, ATS_BSY, 1000000)) {
1689ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic ADBG_WARN(("ata_id_common: "
1690ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic "!DRQ status 0x%x error 0x%x\n",
1691ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic ddi_get8(io_hdl2, (uchar_t *)ioaddr2 +AT_ALTSTATUS),
1692ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR)));
1693ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic return (FALSE);
1694507c3241Smlf }
1695507c3241Smlf }
1696507c3241Smlf
1697507c3241Smlf /*
1698507c3241Smlf * transfer the data
1699507c3241Smlf */
1700507c3241Smlf ddi_rep_get16(io_hdl1, (ushort_t *)aidp, (ushort_t *)ioaddr1 + AT_DATA,
17012df1fe9cSrandyf NBPSCTR >> 1, DDI_DEV_NO_AUTOINCR);
1702507c3241Smlf
1703507c3241Smlf /* wait for the busy bit to settle */
17049f49ae27Smlf ata_nsecwait(400);
1705507c3241Smlf
1706507c3241Smlf
1707507c3241Smlf /*
1708507c3241Smlf * Wait for the drive to recognize I've read all the data.
1709507c3241Smlf * Some drives have been observed to take as much as 3msec to
1710ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic * deassert DRQ after reading the data; allow 1 sec just in case.
1711507c3241Smlf *
1712507c3241Smlf * Note: some non-compliant ATAPI drives (e.g., NEC Multispin 6V,
1713507c3241Smlf * CDR-1350A) don't assert DRDY. If we've made it this far we can
1714507c3241Smlf * safely ignore the DRDY bit since the ATAPI Packet command
1715507c3241Smlf * actually doesn't require it to ever be asserted.
1716507c3241Smlf *
1717ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic * Bail out immediately if the status becomes 0x7f, which is invalid
1718ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic * value. It can happen when no drive is present.
1719ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic *
1720507c3241Smlf */
1721ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic if (!ata_wait3(io_hdl2, ioaddr2, (uchar_t)(expect_drdy ? ATS_DRDY : 0),
1722ab5a7454Svitezslav batrla - Sun Microsystems - Prague Czech Republic (ATS_BSY | ATS_DRQ), 0x7f, ATS_BSY, 0x7f, ATS_BSY, 1000000)) {
1723507c3241Smlf ADBG_WARN(("ata_id_common: bad status 0x%x error 0x%x\n",
17242df1fe9cSrandyf ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS),
17252df1fe9cSrandyf ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR)));
1726507c3241Smlf return (FALSE);
1727507c3241Smlf }
1728507c3241Smlf
1729507c3241Smlf /*
1730507c3241Smlf * Check to see if the command aborted. This happens if
1731507c3241Smlf * an IDENTIFY DEVICE command is issued to an ATAPI PACKET device,
1732507c3241Smlf * or if an IDENTIFY PACKET DEVICE command is issued to an ATA
1733507c3241Smlf * (non-PACKET) device.
1734507c3241Smlf */
1735507c3241Smlf if (status & (ATS_DF | ATS_ERR)) {
1736507c3241Smlf ADBG_WARN(("ata_id_common: status 0x%x error 0x%x \n",
17372df1fe9cSrandyf ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS),
17382df1fe9cSrandyf ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR)));
1739507c3241Smlf return (FALSE);
1740507c3241Smlf }
1741507c3241Smlf return (TRUE);
1742507c3241Smlf }
1743507c3241Smlf
1744507c3241Smlf
1745507c3241Smlf /*
1746507c3241Smlf * Low level routine to issue a non-data command and busy wait for
1747507c3241Smlf * the completion status.
1748507c3241Smlf */
1749507c3241Smlf
1750507c3241Smlf int
ata_command(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,int expect_drdy,int silent,uint_t busy_wait,uchar_t cmd,uchar_t feature,uchar_t count,uchar_t sector,uchar_t head,uchar_t cyl_low,uchar_t cyl_hi)1751507c3241Smlf ata_command(
1752507c3241Smlf ata_ctl_t *ata_ctlp,
1753507c3241Smlf ata_drv_t *ata_drvp,
1754507c3241Smlf int expect_drdy,
1755507c3241Smlf int silent,
1756507c3241Smlf uint_t busy_wait,
1757507c3241Smlf uchar_t cmd,
1758507c3241Smlf uchar_t feature,
1759507c3241Smlf uchar_t count,
1760507c3241Smlf uchar_t sector,
1761507c3241Smlf uchar_t head,
1762507c3241Smlf uchar_t cyl_low,
1763507c3241Smlf uchar_t cyl_hi)
1764507c3241Smlf {
1765507c3241Smlf ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
1766507c3241Smlf ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
1767507c3241Smlf uchar_t status;
1768507c3241Smlf
1769507c3241Smlf /* select the drive */
1770507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, ata_drvp->ad_drive_bits);
17719f49ae27Smlf ata_nsecwait(400);
1772507c3241Smlf
1773507c3241Smlf /* make certain the drive selected */
1774507c3241Smlf if (!ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2,
17752df1fe9cSrandyf (uchar_t)(expect_drdy ? ATS_DRDY : 0),
17762df1fe9cSrandyf ATS_BSY, busy_wait)) {
1777507c3241Smlf ADBG_ERROR(("ata_command: select failed "
17782df1fe9cSrandyf "DRDY 0x%x CMD 0x%x F 0x%x N 0x%x "
17792df1fe9cSrandyf "S 0x%x H 0x%x CL 0x%x CH 0x%x\n",
17802df1fe9cSrandyf expect_drdy, cmd, feature, count,
17812df1fe9cSrandyf sector, head, cyl_low, cyl_hi));
1782507c3241Smlf return (FALSE);
1783507c3241Smlf }
1784507c3241Smlf
1785507c3241Smlf /*
1786507c3241Smlf * set all the regs
1787507c3241Smlf */
1788507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, (head | ata_drvp->ad_drive_bits));
1789507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_sect, sector);
1790507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_count, count);
1791507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_lcyl, cyl_low);
1792507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_hcyl, cyl_hi);
1793507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_feature, feature);
1794507c3241Smlf
1795507c3241Smlf /* send the command */
1796507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_cmd, cmd);
1797507c3241Smlf
1798507c3241Smlf /* wait for the busy bit to settle */
17999f49ae27Smlf ata_nsecwait(400);
1800507c3241Smlf
1801507c3241Smlf /* wait for not busy */
1802507c3241Smlf if (!ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2, 0, ATS_BSY, busy_wait)) {
1803507c3241Smlf ADBG_ERROR(("ata_command: BSY too long!"
18042df1fe9cSrandyf "DRDY 0x%x CMD 0x%x F 0x%x N 0x%x "
18052df1fe9cSrandyf "S 0x%x H 0x%x CL 0x%x CH 0x%x\n",
18062df1fe9cSrandyf expect_drdy, cmd, feature, count,
18072df1fe9cSrandyf sector, head, cyl_low, cyl_hi));
1808507c3241Smlf return (FALSE);
1809507c3241Smlf }
1810507c3241Smlf
1811507c3241Smlf /*
1812507c3241Smlf * wait for DRDY before continuing
1813507c3241Smlf */
1814507c3241Smlf (void) ata_wait3(io_hdl2, ata_ctlp->ac_ioaddr2,
18152df1fe9cSrandyf ATS_DRDY, ATS_BSY, /* okay */
18162df1fe9cSrandyf ATS_ERR, ATS_BSY, /* cmd failed */
18172df1fe9cSrandyf ATS_DF, ATS_BSY, /* drive failed */
18182df1fe9cSrandyf busy_wait);
1819507c3241Smlf
1820507c3241Smlf /* read status to clear IRQ, and check for error */
1821507c3241Smlf status = ddi_get8(io_hdl1, ata_ctlp->ac_status);
1822507c3241Smlf
1823507c3241Smlf if ((status & (ATS_BSY | ATS_DF | ATS_ERR)) == 0)
1824507c3241Smlf return (TRUE);
1825507c3241Smlf
1826507c3241Smlf if (!silent) {
1827507c3241Smlf ADBG_ERROR(("ata_command status 0x%x error 0x%x "
18282df1fe9cSrandyf "DRDY 0x%x CMD 0x%x F 0x%x N 0x%x "
18292df1fe9cSrandyf "S 0x%x H 0x%x CL 0x%x CH 0x%x\n",
18302df1fe9cSrandyf ddi_get8(io_hdl1, ata_ctlp->ac_status),
18312df1fe9cSrandyf ddi_get8(io_hdl1, ata_ctlp->ac_error),
18322df1fe9cSrandyf expect_drdy, cmd, feature, count,
18332df1fe9cSrandyf sector, head, cyl_low, cyl_hi));
1834507c3241Smlf }
1835507c3241Smlf return (FALSE);
1836507c3241Smlf }
1837507c3241Smlf
1838507c3241Smlf
1839507c3241Smlf
1840507c3241Smlf /*
1841507c3241Smlf *
1842507c3241Smlf * Issue a SET FEATURES command
1843507c3241Smlf *
1844507c3241Smlf */
1845507c3241Smlf
1846507c3241Smlf int
ata_set_feature(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,uchar_t feature,uchar_t value)1847507c3241Smlf ata_set_feature(
1848507c3241Smlf ata_ctl_t *ata_ctlp,
1849507c3241Smlf ata_drv_t *ata_drvp,
1850507c3241Smlf uchar_t feature,
1851507c3241Smlf uchar_t value)
1852507c3241Smlf {
1853507c3241Smlf int rc;
1854507c3241Smlf
1855507c3241Smlf rc = ata_command(ata_ctlp, ata_drvp, TRUE, TRUE, ata_set_feature_wait,
18562df1fe9cSrandyf ATC_SET_FEAT, feature, value, 0, 0, 0, 0);
18572df1fe9cSrandyf /* feature, count, sector, head, cyl_low, cyl_hi */
1858507c3241Smlf
1859507c3241Smlf if (rc) {
1860507c3241Smlf return (TRUE);
1861507c3241Smlf }
1862507c3241Smlf
1863507c3241Smlf ADBG_ERROR(("?ata_set_feature: (0x%x,0x%x) failed\n", feature, value));
1864507c3241Smlf return (FALSE);
1865507c3241Smlf }
1866507c3241Smlf
1867507c3241Smlf
1868507c3241Smlf
1869507c3241Smlf /*
1870507c3241Smlf *
1871507c3241Smlf * Issue a FLUSH CACHE command
1872507c3241Smlf *
1873507c3241Smlf */
1874507c3241Smlf
1875507c3241Smlf static int
ata_flush_cache(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp)1876507c3241Smlf ata_flush_cache(
1877507c3241Smlf ata_ctl_t *ata_ctlp,
1878507c3241Smlf ata_drv_t *ata_drvp)
1879507c3241Smlf {
1880507c3241Smlf /* this command is optional so fail silently */
1881507c3241Smlf return (ata_command(ata_ctlp, ata_drvp, TRUE, TRUE,
18822df1fe9cSrandyf ata_flush_cache_wait,
18832df1fe9cSrandyf ATC_FLUSH_CACHE, 0, 0, 0, 0, 0, 0));
1884507c3241Smlf }
1885507c3241Smlf
1886507c3241Smlf /*
1887507c3241Smlf * ata_setup_ioaddr()
1888507c3241Smlf *
1889507c3241Smlf * Map the device registers and return the handles.
1890507c3241Smlf *
1891507c3241Smlf * If this is a ISA-ATA controller then only two handles are
1892507c3241Smlf * initialized and returned.
1893507c3241Smlf *
1894507c3241Smlf * If this is a PCI-IDE controller than a third handle (for the
1895507c3241Smlf * PCI-IDE Bus Mastering registers) is initialized and returned.
1896507c3241Smlf *
1897507c3241Smlf */
1898507c3241Smlf
1899507c3241Smlf static int
ata_setup_ioaddr(dev_info_t * dip,ddi_acc_handle_t * handle1p,caddr_t * addr1p,ddi_acc_handle_t * handle2p,caddr_t * addr2p,ddi_acc_handle_t * bm_hdlp,caddr_t * bm_addrp)1900507c3241Smlf ata_setup_ioaddr(
1901507c3241Smlf dev_info_t *dip,
1902507c3241Smlf ddi_acc_handle_t *handle1p,
1903507c3241Smlf caddr_t *addr1p,
1904507c3241Smlf ddi_acc_handle_t *handle2p,
1905507c3241Smlf caddr_t *addr2p,
1906507c3241Smlf ddi_acc_handle_t *bm_hdlp,
1907507c3241Smlf caddr_t *bm_addrp)
1908507c3241Smlf {
1909507c3241Smlf ddi_device_acc_attr_t dev_attr;
1910507c3241Smlf int rnumber;
1911507c3241Smlf int rc;
1912507c3241Smlf off_t regsize;
1913507c3241Smlf
1914507c3241Smlf /*
1915507c3241Smlf * Make certain the controller is enabled and its regs are map-able
1916507c3241Smlf *
1917507c3241Smlf */
1918507c3241Smlf rc = ddi_dev_regsize(dip, 0, ®size);
1919507c3241Smlf if (rc != DDI_SUCCESS || regsize <= AT_CMD) {
1920507c3241Smlf ADBG_INIT(("ata_setup_ioaddr(1): rc %d regsize %lld\n",
19212df1fe9cSrandyf rc, (long long)regsize));
1922507c3241Smlf return (FALSE);
1923507c3241Smlf }
1924507c3241Smlf
1925507c3241Smlf rc = ddi_dev_regsize(dip, 1, ®size);
1926507c3241Smlf if (rc != DDI_SUCCESS || regsize <= AT_ALTSTATUS) {
1927507c3241Smlf ADBG_INIT(("ata_setup_ioaddr(2): rc %d regsize %lld\n",
19282df1fe9cSrandyf rc, (long long)regsize));
1929507c3241Smlf return (FALSE);
1930507c3241Smlf }
1931507c3241Smlf
1932507c3241Smlf /*
1933507c3241Smlf * setup the device attribute structure for little-endian,
1934507c3241Smlf * strict ordering access.
1935507c3241Smlf */
1936507c3241Smlf dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1937507c3241Smlf dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
1938507c3241Smlf dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1939507c3241Smlf
1940507c3241Smlf *handle1p = NULL;
1941507c3241Smlf *handle2p = NULL;
1942507c3241Smlf *bm_hdlp = NULL;
1943507c3241Smlf
1944507c3241Smlf /*
1945507c3241Smlf * Determine whether this is a ISA, PNP-ISA, or PCI-IDE device
1946507c3241Smlf */
1947507c3241Smlf if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "pnp-csn")) {
1948507c3241Smlf /* it's PNP-ISA, skip over the extra reg tuple */
1949507c3241Smlf rnumber = 1;
1950507c3241Smlf goto not_pciide;
1951507c3241Smlf }
1952507c3241Smlf
1953507c3241Smlf /* else, it's ISA or PCI-IDE, check further */
1954507c3241Smlf rnumber = 0;
1955507c3241Smlf
19562df1fe9cSrandyf if (!ata_is_pci(dip)) {
1957507c3241Smlf /*
1958507c3241Smlf * If it's not a PCI-IDE, there are only two reg tuples
1959507c3241Smlf * and the first one contains the I/O base (170 or 1f0)
1960507c3241Smlf * rather than the controller instance number.
1961507c3241Smlf */
1962507c3241Smlf ADBG_TRACE(("ata_setup_ioaddr !pci-ide\n"));
1963507c3241Smlf goto not_pciide;
1964507c3241Smlf }
1965507c3241Smlf
1966507c3241Smlf
1967507c3241Smlf /*
1968507c3241Smlf * Map the correct half of the PCI-IDE Bus Master registers.
1969507c3241Smlf * There's a single BAR that maps these registers for both
1970507c3241Smlf * controller's in a dual-controller chip and it's upto my
1971507c3241Smlf * parent nexus, pciide, to adjust which (based on my instance
1972507c3241Smlf * number) half this call maps.
1973507c3241Smlf */
1974507c3241Smlf rc = ddi_dev_regsize(dip, 2, ®size);
1975507c3241Smlf if (rc != DDI_SUCCESS || regsize < 8) {
1976507c3241Smlf ADBG_INIT(("ata_setup_ioaddr(3): rc %d regsize %lld\n",
19772df1fe9cSrandyf rc, (long long)regsize));
1978507c3241Smlf goto not_pciide;
1979507c3241Smlf }
1980507c3241Smlf
1981507c3241Smlf rc = ddi_regs_map_setup(dip, 2, bm_addrp, 0, 0, &dev_attr, bm_hdlp);
1982507c3241Smlf
1983507c3241Smlf if (rc != DDI_SUCCESS) {
1984507c3241Smlf /* map failed, try to use in non-pci-ide mode */
1985507c3241Smlf ADBG_WARN(("ata_setup_ioaddr bus master map failed, rc=0x%x\n",
19862df1fe9cSrandyf rc));
1987507c3241Smlf *bm_hdlp = NULL;
1988507c3241Smlf }
1989507c3241Smlf
1990507c3241Smlf not_pciide:
1991507c3241Smlf /*
1992507c3241Smlf * map the lower command block registers
1993507c3241Smlf */
1994507c3241Smlf
1995507c3241Smlf rc = ddi_regs_map_setup(dip, rnumber, addr1p, 0, 0, &dev_attr,
19962df1fe9cSrandyf handle1p);
1997507c3241Smlf
1998507c3241Smlf if (rc != DDI_SUCCESS) {
1999507c3241Smlf cmn_err(CE_WARN, "ata: reg tuple 0 map failed, rc=0x%x\n", rc);
2000507c3241Smlf goto out1;
2001507c3241Smlf }
2002507c3241Smlf
2003507c3241Smlf /*
2004507c3241Smlf * If the controller is being used in compatibility mode
2005507c3241Smlf * via /devices/isa/ata@1,{1f0,1f0}/..., the reg property
2006507c3241Smlf * will specify zeros for the I/O ports for the PCI
2007507c3241Smlf * instance.
2008507c3241Smlf */
2009507c3241Smlf if (*addr1p == 0) {
2010507c3241Smlf ADBG_TRACE(("ata_setup_ioaddr ioaddr1 0\n"));
2011507c3241Smlf goto out2;
2012507c3241Smlf }
2013507c3241Smlf
2014507c3241Smlf /*
2015507c3241Smlf * map the upper control block registers
2016507c3241Smlf */
2017507c3241Smlf rc = ddi_regs_map_setup(dip, rnumber + 1, addr2p, 0, 0, &dev_attr,
20182df1fe9cSrandyf handle2p);
2019507c3241Smlf if (rc == DDI_SUCCESS)
2020507c3241Smlf return (TRUE);
2021507c3241Smlf
2022507c3241Smlf cmn_err(CE_WARN, "ata: reg tuple 1 map failed, rc=0x%x", rc);
2023507c3241Smlf
2024507c3241Smlf out2:
2025507c3241Smlf if (*handle1p != NULL) {
2026507c3241Smlf ddi_regs_map_free(handle1p);
2027507c3241Smlf *handle1p = NULL;
2028507c3241Smlf }
2029507c3241Smlf
2030507c3241Smlf out1:
2031507c3241Smlf if (*bm_hdlp != NULL) {
2032507c3241Smlf ddi_regs_map_free(bm_hdlp);
2033507c3241Smlf *bm_hdlp = NULL;
2034507c3241Smlf }
2035507c3241Smlf return (FALSE);
2036507c3241Smlf
2037507c3241Smlf }
2038507c3241Smlf
2039507c3241Smlf /*
2040507c3241Smlf *
2041507c3241Smlf * Currently, the only supported controllers are ones which
2042507c3241Smlf * support the SFF-8038 Bus Mastering spec.
2043507c3241Smlf *
2044507c3241Smlf * Check the parent node's IEEE 1275 class-code property to
2045507c3241Smlf * determine if it's an PCI-IDE instance which supports SFF-8038
2046507c3241Smlf * Bus Mastering. It's perfectly valid to have a PCI-IDE controller
2047507c3241Smlf * that doesn't do Bus Mastering. In that case, my interrupt handler
2048507c3241Smlf * only uses the interrupt latch bit in PCI-IDE status register.
2049507c3241Smlf * The assumption is that the programming interface byte of the
2050507c3241Smlf * class-code property reflects the bus master DMA capability of
2051507c3241Smlf * the controller.
2052507c3241Smlf *
2053507c3241Smlf * Whether the drive support supports the DMA option still needs
2054507c3241Smlf * to be checked later. Each individual request also has to be
2055507c3241Smlf * checked for alignment and size to decide whether to use the
2056507c3241Smlf * DMA transfer mode.
2057507c3241Smlf */
2058507c3241Smlf
2059507c3241Smlf static void
ata_init_pciide(dev_info_t * dip,ata_ctl_t * ata_ctlp)2060507c3241Smlf ata_init_pciide(
2061507c3241Smlf dev_info_t *dip,
2062507c3241Smlf ata_ctl_t *ata_ctlp)
2063507c3241Smlf {
2064507c3241Smlf uint_t class_code;
2065507c3241Smlf uchar_t status;
2066507c3241Smlf
2067507c3241Smlf ata_cntrl_DMA_sel_msg = NULL;
2068507c3241Smlf
2069507c3241Smlf if (ata_ctlp->ac_bmhandle == NULL) {
2070507c3241Smlf ata_ctlp->ac_pciide = FALSE;
2071507c3241Smlf ata_ctlp->ac_pciide_bm = FALSE;
2072507c3241Smlf ata_cntrl_DMA_sel_msg = "cntrl not Bus Master DMA capable";
2073507c3241Smlf return;
2074507c3241Smlf }
2075507c3241Smlf
2076507c3241Smlf /*
2077507c3241Smlf * check if it's a known bogus PCI-IDE chip
2078507c3241Smlf */
2079507c3241Smlf if (ata_check_pciide_blacklist(dip, ATA_BL_BOGUS)) {
2080507c3241Smlf ADBG_WARN(("ata_setup_ioaddr pci-ide blacklist\n"));
2081507c3241Smlf ata_ctlp->ac_pciide = FALSE;
2082507c3241Smlf ata_ctlp->ac_pciide_bm = FALSE;
2083507c3241Smlf ata_cntrl_DMA_sel_msg = "cntrl blacklisted";
2084507c3241Smlf return;
2085507c3241Smlf }
2086507c3241Smlf ata_ctlp->ac_pciide = TRUE;
2087507c3241Smlf
2088507c3241Smlf if (ata_check_pciide_blacklist(dip, ATA_BL_BMSTATREG_PIO_BROKEN)) {
2089507c3241Smlf ata_ctlp->ac_flags |= AC_BMSTATREG_PIO_BROKEN;
2090507c3241Smlf }
2091507c3241Smlf
2092507c3241Smlf /*
2093507c3241Smlf * check for a PCI-IDE chip with a broken DMA engine
2094507c3241Smlf */
2095507c3241Smlf if (ata_check_pciide_blacklist(dip, ATA_BL_NODMA)) {
2096507c3241Smlf ata_ctlp->ac_pciide_bm = FALSE;
2097507c3241Smlf ata_cntrl_DMA_sel_msg =
20982df1fe9cSrandyf "cntrl blacklisted/DMA engine broken";
2099507c3241Smlf return;
2100507c3241Smlf }
2101507c3241Smlf
2102507c3241Smlf /*
2103507c3241Smlf * Check the Programming Interface register to determine
2104507c3241Smlf * if this device supports PCI-IDE Bus Mastering. Some PCI-IDE
2105507c3241Smlf * devices don't support Bus Mastering or DMA.
2106507c3241Smlf * Since we are dealing with pre-qualified pci-ide controller,
2107507c3241Smlf * check programming interface byte only.
2108507c3241Smlf */
2109507c3241Smlf
2110507c3241Smlf class_code = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip),
21112df1fe9cSrandyf DDI_PROP_DONTPASS, "class-code", 0);
2112507c3241Smlf if ((class_code & PCIIDE_BM_CAP_MASK) != PCIIDE_BM_CAP_MASK) {
2113507c3241Smlf ata_ctlp->ac_pciide_bm = FALSE;
2114507c3241Smlf ata_cntrl_DMA_sel_msg =
21152df1fe9cSrandyf "cntrl not Bus Master DMA capable";
2116507c3241Smlf return;
2117507c3241Smlf }
2118507c3241Smlf
2119507c3241Smlf /*
2120507c3241Smlf * Avoid doing DMA on "simplex" chips which share hardware
2121507c3241Smlf * between channels
2122507c3241Smlf */
2123507c3241Smlf status = ddi_get8(ata_ctlp->ac_bmhandle,
21242df1fe9cSrandyf (uchar_t *)ata_ctlp->ac_bmaddr + PCIIDE_BMISX_REG);
2125507c3241Smlf /*
2126507c3241Smlf * Some motherboards have CSB5's that are wired "to emulate CSB4 mode".
2127507c3241Smlf * In such a mode, the simplex bit is asserted, but in fact testing
2128507c3241Smlf * on such a motherboard has shown that the devices are not simplex
2129507c3241Smlf * -- DMA can be used on both channels concurrently with no special
2130507c3241Smlf * considerations. For chips like this, we have the ATA_BL_NO_SIMPLEX
2131507c3241Smlf * flag set to indicate that the value of the simplex bit can be
2132507c3241Smlf * ignored.
2133507c3241Smlf */
2134507c3241Smlf
2135507c3241Smlf if (status & PCIIDE_BMISX_SIMPLEX) {
2136d39757aaSmlf if (ata_check_pciide_blacklist(dip, ATA_BL_NO_SIMPLEX)) {
2137507c3241Smlf cmn_err(CE_WARN, "Ignoring false simplex bit \n");
2138d39757aaSmlf
2139507c3241Smlf } else {
2140d39757aaSmlf
2141d39757aaSmlf int simplex_dma_channel, *rp, proplen, channel;
2142d39757aaSmlf int dma_on = FALSE;
2143d39757aaSmlf
2144d39757aaSmlf /*
2145d39757aaSmlf * By default,use DMA on channel 0 and PIO on channel
2146d39757aaSmlf * 1. This can be switched by setting
2147d39757aaSmlf * ata-simplex-dma-channel to:
2148d39757aaSmlf * 0 DMA on channel 0 (default without this
2149d39757aaSmlf * property)
2150d39757aaSmlf * 1 DMA on channel 1
2151d39757aaSmlf * any other value: DMA off on both channels.
2152d39757aaSmlf */
2153d39757aaSmlf simplex_dma_channel = ata_prop_lookup_int(DDI_DEV_T_ANY,
2154d39757aaSmlf ata_ctlp->ac_dip, 0, "ata-simplex-dma-channel", 0);
2155d39757aaSmlf
2156d39757aaSmlf if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
2157d39757aaSmlf ata_ctlp->ac_dip, DDI_PROP_DONTPASS, "reg", &rp,
2158d39757aaSmlf (uint_t *)&proplen) == DDI_PROP_SUCCESS) {
2159d39757aaSmlf
2160d39757aaSmlf channel = *rp;
2161d39757aaSmlf ddi_prop_free(rp);
2162d39757aaSmlf
2163d39757aaSmlf if (simplex_dma_channel == channel) {
2164ab4f33c9Sml cmn_err(CE_CONT, "?ata: simplex "
2165d39757aaSmlf "controller. DMA on channel"
2166ab4f33c9Sml " %d PIO on channel %d",
2167d39757aaSmlf channel, channel ? 0:1);
2168d39757aaSmlf dma_on = TRUE;
2169d39757aaSmlf } else {
2170d39757aaSmlf ata_cntrl_DMA_sel_msg =
2171d39757aaSmlf "simplex controller";
2172d39757aaSmlf }
2173d39757aaSmlf }
2174d39757aaSmlf
2175d39757aaSmlf if (dma_on == FALSE) {
2176d39757aaSmlf ata_ctlp->ac_pciide_bm = FALSE;
2177d39757aaSmlf
2178d39757aaSmlf return;
2179d39757aaSmlf }
2180507c3241Smlf }
2181507c3241Smlf }
2182507c3241Smlf
2183507c3241Smlf /*
2184507c3241Smlf * It's a compatible PCI-IDE Bus Mastering controller,
2185507c3241Smlf * allocate and map the DMA Scatter/Gather list (PRDE table).
2186507c3241Smlf */
2187507c3241Smlf if (ata_pciide_alloc(dip, ata_ctlp))
2188507c3241Smlf ata_ctlp->ac_pciide_bm = TRUE;
2189507c3241Smlf else {
2190507c3241Smlf ata_ctlp->ac_pciide_bm = FALSE;
2191507c3241Smlf ata_cntrl_DMA_sel_msg = "unable to init DMA S/G list";
2192507c3241Smlf }
2193507c3241Smlf }
2194507c3241Smlf
2195507c3241Smlf /*
2196507c3241Smlf *
2197507c3241Smlf * Determine whether to enable DMA support for this drive.
2198507c3241Smlf * The controller and the drive both have to support DMA.
2199507c3241Smlf * The controller's capabilities were already checked in
2200507c3241Smlf * ata_init_pciide(), now just check the drive's capabilities.
2201507c3241Smlf *
2202507c3241Smlf */
2203507c3241Smlf
2204507c3241Smlf static int
ata_init_drive_pcidma(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,dev_info_t * tdip)2205507c3241Smlf ata_init_drive_pcidma(
2206507c3241Smlf ata_ctl_t *ata_ctlp,
2207507c3241Smlf ata_drv_t *ata_drvp,
2208507c3241Smlf dev_info_t *tdip)
2209507c3241Smlf {
2210507c3241Smlf boolean_t dma;
2211507c3241Smlf boolean_t cd_dma;
2212507c3241Smlf boolean_t disk_dma;
2213507c3241Smlf boolean_t atapi_dma;
2214507c3241Smlf int ata_options;
2215507c3241Smlf
2216507c3241Smlf ata_dev_DMA_sel_msg = NULL;
2217507c3241Smlf
2218507c3241Smlf if (ata_ctlp->ac_pciide_bm != TRUE) {
2219507c3241Smlf ata_dev_DMA_sel_msg =
2220507c3241Smlf "controller is not Bus Master capable";
2221507c3241Smlf
2222507c3241Smlf return (ATA_DMA_OFF);
2223507c3241Smlf }
2224507c3241Smlf
2225507c3241Smlf ata_options = ddi_prop_get_int(DDI_DEV_T_ANY, ata_ctlp->ac_dip,
22262df1fe9cSrandyf 0, "ata-options", 0);
2227507c3241Smlf
2228507c3241Smlf if (!(ata_options & ATA_OPTIONS_DMA)) {
2229507c3241Smlf /*
2230507c3241Smlf * Either the ata-options property was not found or
2231507c3241Smlf * DMA is not enabled by this property
2232507c3241Smlf */
2233507c3241Smlf ata_dev_DMA_sel_msg =
22342df1fe9cSrandyf "disabled by \"ata-options\" property";
2235507c3241Smlf
2236507c3241Smlf return (ATA_DMA_OFF);
2237507c3241Smlf }
2238507c3241Smlf
2239507c3241Smlf if (ata_check_drive_blacklist(&ata_drvp->ad_id, ATA_BL_NODMA)) {
2240507c3241Smlf ata_dev_DMA_sel_msg = "device not DMA capable; blacklisted";
2241507c3241Smlf
2242507c3241Smlf return (ATA_DMA_OFF);
2243507c3241Smlf }
2244507c3241Smlf
2245507c3241Smlf /*
2246507c3241Smlf * DMA mode is mandatory on ATA-3 (or newer) drives but is
2247507c3241Smlf * optional on ATA-2 (or older) drives.
2248507c3241Smlf *
2249507c3241Smlf * On ATA-2 drives the ai_majorversion word will probably
2250507c3241Smlf * be 0xffff or 0x0000, check the (now obsolete) DMA bit in
2251507c3241Smlf * the capabilities word instead. The order of these tests
2252507c3241Smlf * is important since an ATA-3 drive doesn't have to set
2253507c3241Smlf * the DMA bit in the capabilities word.
2254507c3241Smlf *
2255507c3241Smlf */
2256507c3241Smlf
2257507c3241Smlf if (!((ata_drvp->ad_id.ai_majorversion & 0x8000) == 0 &&
2258507c3241Smlf ata_drvp->ad_id.ai_majorversion >= (1 << 2)) &&
2259507c3241Smlf !(ata_drvp->ad_id.ai_cap & ATAC_DMA_SUPPORT)) {
2260507c3241Smlf ata_dev_DMA_sel_msg = "device not DMA capable";
2261507c3241Smlf
2262507c3241Smlf return (ATA_DMA_OFF);
2263507c3241Smlf }
2264507c3241Smlf
2265f304523cSzhongyan gu - Sun Microsystems - Beijing China /*
2266f304523cSzhongyan gu - Sun Microsystems - Beijing China * Disable DMA for ATAPI devices on controllers known to
2267f304523cSzhongyan gu - Sun Microsystems - Beijing China * have trouble with ATAPI DMA
2268f304523cSzhongyan gu - Sun Microsystems - Beijing China */
2269f304523cSzhongyan gu - Sun Microsystems - Beijing China
2270f304523cSzhongyan gu - Sun Microsystems - Beijing China if (ATAPIDRV(ata_drvp)) {
2271f304523cSzhongyan gu - Sun Microsystems - Beijing China if (ata_check_pciide_blacklist(ata_ctlp->ac_dip,
2272f304523cSzhongyan gu - Sun Microsystems - Beijing China ATA_BL_ATAPI_NODMA)) {
2273f304523cSzhongyan gu - Sun Microsystems - Beijing China ata_dev_DMA_sel_msg =
2274f304523cSzhongyan gu - Sun Microsystems - Beijing China "controller incapable of DMA for ATAPI device";
2275f304523cSzhongyan gu - Sun Microsystems - Beijing China
2276f304523cSzhongyan gu - Sun Microsystems - Beijing China return (ATA_DMA_OFF);
2277f304523cSzhongyan gu - Sun Microsystems - Beijing China }
2278f304523cSzhongyan gu - Sun Microsystems - Beijing China }
2279507c3241Smlf dma = ata_prop_lookup_int(DDI_DEV_T_ANY, tdip,
22802df1fe9cSrandyf 0, "ata-dma-enabled", TRUE);
2281507c3241Smlf disk_dma = ata_prop_lookup_int(DDI_DEV_T_ANY, tdip,
22822df1fe9cSrandyf 0, "ata-disk-dma-enabled", TRUE);
2283507c3241Smlf cd_dma = ata_prop_lookup_int(DDI_DEV_T_ANY, tdip,
22842df1fe9cSrandyf 0, "atapi-cd-dma-enabled", FALSE);
2285507c3241Smlf atapi_dma = ata_prop_lookup_int(DDI_DEV_T_ANY, tdip,
22862df1fe9cSrandyf 0, "atapi-other-dma-enabled", TRUE);
2287507c3241Smlf
2288507c3241Smlf if (dma == FALSE) {
2289507c3241Smlf cmn_err(CE_CONT, "?ata_init_drive_pcidma: "
2290507c3241Smlf "DMA disabled by \"ata-dma-enabled\" property");
2291507c3241Smlf ata_dev_DMA_sel_msg = "disabled by prop ata-dma-enabled";
2292507c3241Smlf
2293507c3241Smlf return (ATA_DMA_OFF);
2294507c3241Smlf }
2295507c3241Smlf
2296507c3241Smlf if (IS_CDROM(ata_drvp) == TRUE) {
2297507c3241Smlf if (cd_dma == FALSE) {
2298507c3241Smlf ata_dev_DMA_sel_msg =
2299507c3241Smlf "disabled. Control with \"atapi-cd-dma-enabled\""
2300507c3241Smlf " property";
2301507c3241Smlf
2302507c3241Smlf return (ATA_DMA_OFF);
2303507c3241Smlf }
2304507c3241Smlf
2305507c3241Smlf } else if (ATAPIDRV(ata_drvp) == FALSE) {
2306507c3241Smlf if (disk_dma == FALSE) {
2307507c3241Smlf ata_dev_DMA_sel_msg =
2308507c3241Smlf "disabled by \"ata-disk-dma-enabled\" property";
2309507c3241Smlf
2310507c3241Smlf return (ATA_DMA_OFF);
2311507c3241Smlf }
2312507c3241Smlf
2313507c3241Smlf } else if (atapi_dma == FALSE) {
2314507c3241Smlf ata_dev_DMA_sel_msg =
2315507c3241Smlf "disabled by \"atapi-other-dma-enabled\" property";
2316507c3241Smlf
2317507c3241Smlf return (ATA_DMA_OFF);
2318507c3241Smlf }
2319507c3241Smlf
2320507c3241Smlf return (ATA_DMA_ON);
2321507c3241Smlf }
2322507c3241Smlf
2323507c3241Smlf
2324507c3241Smlf
2325507c3241Smlf /*
2326507c3241Smlf * this compare routine squeezes out extra blanks and
2327507c3241Smlf * returns TRUE if p1 matches the leftmost substring of p2
2328507c3241Smlf */
2329507c3241Smlf
2330507c3241Smlf static int
ata_strncmp(char * p1,char * p2,int cnt)2331507c3241Smlf ata_strncmp(
2332507c3241Smlf char *p1,
2333507c3241Smlf char *p2,
2334507c3241Smlf int cnt)
2335507c3241Smlf {
2336507c3241Smlf
2337507c3241Smlf for (;;) {
2338507c3241Smlf /*
2339507c3241Smlf * skip over any extra blanks in both strings
2340507c3241Smlf */
2341507c3241Smlf while (*p1 != '\0' && *p1 == ' ')
2342507c3241Smlf p1++;
2343507c3241Smlf
2344507c3241Smlf while (cnt != 0 && *p2 == ' ') {
2345507c3241Smlf p2++;
2346507c3241Smlf cnt--;
2347507c3241Smlf }
2348507c3241Smlf
2349507c3241Smlf /*
2350507c3241Smlf * compare the two strings
2351507c3241Smlf */
2352507c3241Smlf
2353507c3241Smlf if (cnt == 0 || *p1 != *p2)
2354507c3241Smlf break;
2355507c3241Smlf
2356507c3241Smlf while (cnt > 0 && *p1 == *p2) {
2357507c3241Smlf p1++;
2358507c3241Smlf p2++;
2359507c3241Smlf cnt--;
2360507c3241Smlf }
2361507c3241Smlf
2362507c3241Smlf }
2363507c3241Smlf
2364507c3241Smlf /* return TRUE if both strings ended at same point */
2365507c3241Smlf return ((*p1 == '\0') ? TRUE : FALSE);
2366507c3241Smlf }
2367507c3241Smlf
2368507c3241Smlf /*
2369507c3241Smlf * Per PSARC/1997/281 create variant="atapi" property (if necessary)
2370507c3241Smlf * on the target's dev_info node. Currently, the sd target driver
2371507c3241Smlf * is the only driver which refers to this property.
2372507c3241Smlf *
2373507c3241Smlf * If the flag ata_id_debug is set also create the
2374507c3241Smlf * the "ata" or "atapi" property on the target's dev_info node
2375507c3241Smlf *
2376507c3241Smlf */
2377507c3241Smlf
2378507c3241Smlf int
ata_prop_create(dev_info_t * tgt_dip,ata_drv_t * ata_drvp,char * name)2379507c3241Smlf ata_prop_create(
2380507c3241Smlf dev_info_t *tgt_dip,
2381507c3241Smlf ata_drv_t *ata_drvp,
2382507c3241Smlf char *name)
2383507c3241Smlf {
2384507c3241Smlf int rc;
2385507c3241Smlf
2386507c3241Smlf ADBG_TRACE(("ata_prop_create 0x%p 0x%p %s\n", tgt_dip, ata_drvp, name));
2387507c3241Smlf
2388507c3241Smlf if (strcmp("atapi", name) == 0) {
2389507c3241Smlf rc = ndi_prop_update_string(DDI_DEV_T_NONE, tgt_dip,
23902df1fe9cSrandyf "variant", name);
2391507c3241Smlf if (rc != DDI_PROP_SUCCESS)
2392507c3241Smlf return (FALSE);
2393507c3241Smlf }
2394507c3241Smlf
2395507c3241Smlf if (!ata_id_debug)
2396507c3241Smlf return (TRUE);
2397507c3241Smlf
2398507c3241Smlf rc = ndi_prop_update_byte_array(DDI_DEV_T_NONE, tgt_dip, name,
23992df1fe9cSrandyf (uchar_t *)&ata_drvp->ad_id, sizeof (ata_drvp->ad_id));
2400507c3241Smlf if (rc != DDI_PROP_SUCCESS) {
2401507c3241Smlf ADBG_ERROR(("ata_prop_create failed, rc=%d\n", rc));
2402507c3241Smlf }
2403507c3241Smlf return (TRUE);
2404507c3241Smlf }
2405507c3241Smlf
2406507c3241Smlf
2407507c3241Smlf /* *********************************************************************** */
2408507c3241Smlf /* *********************************************************************** */
2409507c3241Smlf /* *********************************************************************** */
2410507c3241Smlf
2411507c3241Smlf /*
2412507c3241Smlf * This state machine doesn't implement the ATAPI Optional Overlap
2413507c3241Smlf * feature. You need that feature to efficiently support ATAPI
2414507c3241Smlf * tape drives. See the 1394-ATA Tailgate spec (D97107), Figure 24,
2415507c3241Smlf * for an example of how to add the necessary additional NextActions
2416507c3241Smlf * and NextStates to this FSM and the atapi_fsm, in order to support
2417507c3241Smlf * the Overlap Feature.
2418507c3241Smlf */
2419507c3241Smlf
2420507c3241Smlf
2421507c3241Smlf uchar_t ata_ctlr_fsm_NextAction[ATA_CTLR_NSTATES][ATA_CTLR_NFUNCS] = {
2422507c3241Smlf /* --------------------- next action --------------------- | - current - */
2423507c3241Smlf /* start0 --- start1 ---- intr ------ fini --- reset --- */
2424507c3241Smlf { AC_START, AC_START, AC_NADA, AC_NADA, AC_RESET_I }, /* idle */
2425507c3241Smlf { AC_BUSY, AC_BUSY, AC_INTR, AC_FINI, AC_RESET_A }, /* active0 */
2426507c3241Smlf { AC_BUSY, AC_BUSY, AC_INTR, AC_FINI, AC_RESET_A }, /* active1 */
2427507c3241Smlf };
2428507c3241Smlf
2429507c3241Smlf uchar_t ata_ctlr_fsm_NextState[ATA_CTLR_NSTATES][ATA_CTLR_NFUNCS] = {
2430507c3241Smlf
2431507c3241Smlf /* --------------------- next state --------------------- | - current - */
2432507c3241Smlf /* start0 --- start1 ---- intr ------ fini --- reset --- */
2433507c3241Smlf { AS_ACTIVE0, AS_ACTIVE1, AS_IDLE, AS_IDLE, AS_IDLE }, /* idle */
2434507c3241Smlf { AS_ACTIVE0, AS_ACTIVE0, AS_ACTIVE0, AS_IDLE, AS_ACTIVE0 }, /* active0 */
2435507c3241Smlf { AS_ACTIVE1, AS_ACTIVE1, AS_ACTIVE1, AS_IDLE, AS_ACTIVE1 }, /* active1 */
2436507c3241Smlf };
2437507c3241Smlf
2438507c3241Smlf
2439507c3241Smlf static int
ata_ctlr_fsm(uchar_t fsm_func,ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp,int * DoneFlgp)2440507c3241Smlf ata_ctlr_fsm(
2441507c3241Smlf uchar_t fsm_func,
2442507c3241Smlf ata_ctl_t *ata_ctlp,
2443507c3241Smlf ata_drv_t *ata_drvp,
2444507c3241Smlf ata_pkt_t *ata_pktp,
2445507c3241Smlf int *DoneFlgp)
2446507c3241Smlf {
2447507c3241Smlf uchar_t action;
2448507c3241Smlf uchar_t current_state;
2449507c3241Smlf uchar_t next_state;
2450507c3241Smlf int rc;
2451507c3241Smlf
2452507c3241Smlf current_state = ata_ctlp->ac_state;
2453507c3241Smlf action = ata_ctlr_fsm_NextAction[current_state][fsm_func];
2454507c3241Smlf next_state = ata_ctlr_fsm_NextState[current_state][fsm_func];
2455507c3241Smlf
2456507c3241Smlf /*
2457507c3241Smlf * Set the controller's new state
2458507c3241Smlf */
2459507c3241Smlf ata_ctlp->ac_state = next_state;
2460507c3241Smlf switch (action) {
2461507c3241Smlf
2462507c3241Smlf case AC_BUSY:
2463507c3241Smlf return (ATA_FSM_RC_BUSY);
2464507c3241Smlf
2465507c3241Smlf case AC_NADA:
2466507c3241Smlf return (ATA_FSM_RC_OKAY);
2467507c3241Smlf
2468507c3241Smlf case AC_START:
2469507c3241Smlf ASSERT(ata_ctlp->ac_active_pktp == NULL);
2470507c3241Smlf ASSERT(ata_ctlp->ac_active_drvp == NULL);
2471507c3241Smlf
2472507c3241Smlf ata_ctlp->ac_active_pktp = ata_pktp;
2473507c3241Smlf ata_ctlp->ac_active_drvp = ata_drvp;
2474507c3241Smlf
2475507c3241Smlf rc = (*ata_pktp->ap_start)(ata_ctlp, ata_drvp, ata_pktp);
2476507c3241Smlf
2477507c3241Smlf if (rc == ATA_FSM_RC_BUSY) {
2478507c3241Smlf /* the request didn't start, GHD will requeue it */
2479507c3241Smlf ata_ctlp->ac_state = AS_IDLE;
2480507c3241Smlf ata_ctlp->ac_active_pktp = NULL;
2481507c3241Smlf ata_ctlp->ac_active_drvp = NULL;
2482507c3241Smlf }
2483507c3241Smlf return (rc);
2484507c3241Smlf
2485507c3241Smlf case AC_INTR:
2486507c3241Smlf ASSERT(ata_ctlp->ac_active_pktp != NULL);
2487507c3241Smlf ASSERT(ata_ctlp->ac_active_drvp != NULL);
2488507c3241Smlf
2489507c3241Smlf ata_drvp = ata_ctlp->ac_active_drvp;
2490507c3241Smlf ata_pktp = ata_ctlp->ac_active_pktp;
2491507c3241Smlf return ((*ata_pktp->ap_intr)(ata_ctlp, ata_drvp, ata_pktp));
2492507c3241Smlf
2493507c3241Smlf case AC_RESET_A: /* Reset, controller active */
2494507c3241Smlf ASSERT(ata_ctlp->ac_active_pktp != NULL);
2495507c3241Smlf ASSERT(ata_ctlp->ac_active_drvp != NULL);
2496507c3241Smlf
2497507c3241Smlf /* clean up the active request */
2498507c3241Smlf ata_pktp = ata_ctlp->ac_active_pktp;
2499507c3241Smlf ata_pktp->ap_flags |= AP_DEV_RESET | AP_BUS_RESET;
2500507c3241Smlf
2501507c3241Smlf /* halt the DMA engine */
2502507c3241Smlf if (ata_pktp->ap_pciide_dma) {
2503507c3241Smlf ata_pciide_dma_stop(ata_ctlp);
2504507c3241Smlf (void) ata_pciide_status_clear(ata_ctlp);
2505507c3241Smlf }
2506507c3241Smlf
2507507c3241Smlf /* Do a Software Reset to unwedge the bus */
2508507c3241Smlf if (!ata_software_reset(ata_ctlp)) {
2509507c3241Smlf return (ATA_FSM_RC_BUSY);
2510507c3241Smlf }
2511507c3241Smlf
2512507c3241Smlf /* Then send a DEVICE RESET cmd to each ATAPI device */
2513507c3241Smlf atapi_fsm_reset(ata_ctlp);
2514507c3241Smlf return (ATA_FSM_RC_FINI);
2515507c3241Smlf
2516507c3241Smlf case AC_RESET_I: /* Reset, controller idle */
2517507c3241Smlf /* Do a Software Reset to unwedge the bus */
2518507c3241Smlf if (!ata_software_reset(ata_ctlp)) {
2519507c3241Smlf return (ATA_FSM_RC_BUSY);
2520507c3241Smlf }
2521507c3241Smlf
2522507c3241Smlf /* Then send a DEVICE RESET cmd to each ATAPI device */
2523507c3241Smlf atapi_fsm_reset(ata_ctlp);
2524507c3241Smlf return (ATA_FSM_RC_OKAY);
2525507c3241Smlf
2526507c3241Smlf case AC_FINI:
2527507c3241Smlf break;
2528507c3241Smlf }
2529507c3241Smlf
2530507c3241Smlf /*
2531507c3241Smlf * AC_FINI, check ARQ needs to be started or finished
2532507c3241Smlf */
2533507c3241Smlf
2534507c3241Smlf ASSERT(action == AC_FINI);
2535507c3241Smlf ASSERT(ata_ctlp->ac_active_pktp != NULL);
2536507c3241Smlf ASSERT(ata_ctlp->ac_active_drvp != NULL);
2537507c3241Smlf
2538507c3241Smlf /*
2539507c3241Smlf * The active request is done now.
2540507c3241Smlf * Disconnect the request from the controller and
2541507c3241Smlf * add it to the done queue.
2542507c3241Smlf */
2543507c3241Smlf ata_drvp = ata_ctlp->ac_active_drvp;
2544507c3241Smlf ata_pktp = ata_ctlp->ac_active_pktp;
2545507c3241Smlf
2546507c3241Smlf /*
2547507c3241Smlf * If ARQ pkt is done, get ptr to original pkt and wrap it up.
2548507c3241Smlf */
2549507c3241Smlf if (ata_pktp == ata_ctlp->ac_arq_pktp) {
2550507c3241Smlf ata_pkt_t *arq_pktp;
2551507c3241Smlf
2552507c3241Smlf ADBG_ARQ(("ata_ctlr_fsm 0x%p ARQ done\n", ata_ctlp));
2553507c3241Smlf
2554507c3241Smlf arq_pktp = ata_pktp;
2555507c3241Smlf ata_pktp = ata_ctlp->ac_fault_pktp;
2556507c3241Smlf ata_ctlp->ac_fault_pktp = NULL;
2557507c3241Smlf if (arq_pktp->ap_flags & (AP_ERROR | AP_BUS_RESET))
2558507c3241Smlf ata_pktp->ap_flags |= AP_ARQ_ERROR;
2559507c3241Smlf else
2560507c3241Smlf ata_pktp->ap_flags |= AP_ARQ_OKAY;
2561507c3241Smlf goto all_done;
2562507c3241Smlf }
2563507c3241Smlf
2564507c3241Smlf
2565507c3241Smlf #define AP_ARQ_NEEDED (AP_ARQ_ON_ERROR | AP_GOT_STATUS | AP_ERROR)
2566507c3241Smlf
2567507c3241Smlf /*
2568507c3241Smlf * Start ARQ pkt if necessary
2569507c3241Smlf */
2570507c3241Smlf if ((ata_pktp->ap_flags & AP_ARQ_NEEDED) == AP_ARQ_NEEDED &&
25712df1fe9cSrandyf (ata_pktp->ap_status & ATS_ERR)) {
2572507c3241Smlf
2573507c3241Smlf /* set controller state back to active */
2574507c3241Smlf ata_ctlp->ac_state = current_state;
2575507c3241Smlf
2576507c3241Smlf /* try to start the ARQ pkt */
2577507c3241Smlf rc = ata_start_arq(ata_ctlp, ata_drvp, ata_pktp);
2578507c3241Smlf
2579507c3241Smlf if (rc == ATA_FSM_RC_BUSY) {
2580507c3241Smlf ADBG_ARQ(("ata_ctlr_fsm 0x%p ARQ BUSY\n", ata_ctlp));
2581507c3241Smlf /* let the target driver handle the problem */
2582507c3241Smlf ata_ctlp->ac_state = AS_IDLE;
2583507c3241Smlf ata_ctlp->ac_active_pktp = NULL;
2584507c3241Smlf ata_ctlp->ac_active_drvp = NULL;
2585507c3241Smlf ata_ctlp->ac_fault_pktp = NULL;
2586507c3241Smlf goto all_done;
2587507c3241Smlf }
2588507c3241Smlf
2589507c3241Smlf ADBG_ARQ(("ata_ctlr_fsm 0x%p ARQ started\n", ata_ctlp));
2590507c3241Smlf return (rc);
2591507c3241Smlf }
2592507c3241Smlf
2593507c3241Smlf /*
2594507c3241Smlf * Normal completion, no error status, and not an ARQ pkt,
2595507c3241Smlf * just fall through.
2596507c3241Smlf */
2597507c3241Smlf
2598507c3241Smlf all_done:
2599507c3241Smlf
2600507c3241Smlf /*
2601507c3241Smlf * wrap everything up and tie a ribbon around it
2602507c3241Smlf */
2603507c3241Smlf ata_ctlp->ac_active_pktp = NULL;
2604507c3241Smlf ata_ctlp->ac_active_drvp = NULL;
2605507c3241Smlf if (APKT2GCMD(ata_pktp) != (gcmd_t *)0) {
2606507c3241Smlf ghd_complete(&ata_ctlp->ac_ccc, APKT2GCMD(ata_pktp));
2607507c3241Smlf if (DoneFlgp)
2608507c3241Smlf *DoneFlgp = TRUE;
2609507c3241Smlf }
2610507c3241Smlf
2611507c3241Smlf return (ATA_FSM_RC_OKAY);
2612507c3241Smlf }
2613507c3241Smlf
2614507c3241Smlf
2615507c3241Smlf static int
ata_start_arq(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,ata_pkt_t * ata_pktp)2616507c3241Smlf ata_start_arq(
2617507c3241Smlf ata_ctl_t *ata_ctlp,
2618507c3241Smlf ata_drv_t *ata_drvp,
2619507c3241Smlf ata_pkt_t *ata_pktp)
2620507c3241Smlf {
2621507c3241Smlf ata_pkt_t *arq_pktp;
2622507c3241Smlf int bytes;
2623507c3241Smlf uint_t senselen;
2624507c3241Smlf
2625507c3241Smlf ADBG_ARQ(("ata_start_arq 0x%p ARQ needed\n", ata_ctlp));
2626507c3241Smlf
2627507c3241Smlf /*
2628507c3241Smlf * Determine just the size of the Request Sense Data buffer within
2629507c3241Smlf * the scsi_arq_status structure.
2630507c3241Smlf */
2631507c3241Smlf #define SIZEOF_ARQ_HEADER (sizeof (struct scsi_arq_status) \
2632507c3241Smlf - sizeof (struct scsi_extended_sense))
2633507c3241Smlf senselen = ata_pktp->ap_statuslen - SIZEOF_ARQ_HEADER;
2634507c3241Smlf ASSERT(senselen > 0);
2635507c3241Smlf
2636507c3241Smlf
2637507c3241Smlf /* save ptr to original pkt */
2638507c3241Smlf ata_ctlp->ac_fault_pktp = ata_pktp;
2639507c3241Smlf
2640507c3241Smlf /* switch the controller's active pkt to the ARQ pkt */
2641507c3241Smlf arq_pktp = ata_ctlp->ac_arq_pktp;
2642507c3241Smlf ata_ctlp->ac_active_pktp = arq_pktp;
2643507c3241Smlf
2644507c3241Smlf /* finish initializing the ARQ CDB */
2645507c3241Smlf ata_ctlp->ac_arq_cdb[1] = ata_drvp->ad_lun << 4;
2646f304523cSzhongyan gu - Sun Microsystems - Beijing China ata_ctlp->ac_arq_cdb[4] = (uchar_t)senselen;
2647507c3241Smlf
2648507c3241Smlf /* finish initializing the ARQ pkt */
2649507c3241Smlf arq_pktp->ap_v_addr = (caddr_t)&ata_pktp->ap_scbp->sts_sensedata;
2650507c3241Smlf
2651507c3241Smlf arq_pktp->ap_resid = senselen;
2652507c3241Smlf arq_pktp->ap_flags = AP_ATAPI | AP_READ;
2653507c3241Smlf arq_pktp->ap_cdb_pad =
26542df1fe9cSrandyf ((unsigned)(ata_drvp->ad_cdb_len - arq_pktp->ap_cdb_len)) >> 1;
2655507c3241Smlf
2656507c3241Smlf bytes = min(senselen, ATAPI_MAX_BYTES_PER_DRQ);
2657507c3241Smlf arq_pktp->ap_hicyl = (uchar_t)(bytes >> 8);
2658507c3241Smlf arq_pktp->ap_lwcyl = (uchar_t)bytes;
2659507c3241Smlf
2660507c3241Smlf /*
2661507c3241Smlf * This packet is shared by all drives on this controller
2662507c3241Smlf * therefore we need to init the drive number on every ARQ.
2663507c3241Smlf */
2664507c3241Smlf arq_pktp->ap_hd = ata_drvp->ad_drive_bits;
2665507c3241Smlf
2666507c3241Smlf /* start it up */
2667507c3241Smlf return ((*arq_pktp->ap_start)(ata_ctlp, ata_drvp, arq_pktp));
2668507c3241Smlf }
2669507c3241Smlf
2670507c3241Smlf /*
2671507c3241Smlf *
2672507c3241Smlf * reset the bus
2673507c3241Smlf *
2674507c3241Smlf */
2675507c3241Smlf
2676507c3241Smlf static int
ata_reset_bus(ata_ctl_t * ata_ctlp)2677507c3241Smlf ata_reset_bus(
2678507c3241Smlf ata_ctl_t *ata_ctlp)
2679507c3241Smlf {
2680507c3241Smlf int watchdog;
2681507c3241Smlf uchar_t drive;
2682507c3241Smlf int rc = FALSE;
2683507c3241Smlf uchar_t fsm_func;
2684507c3241Smlf int DoneFlg = FALSE;
2685507c3241Smlf
2686507c3241Smlf /*
2687507c3241Smlf * Do a Software Reset to unwedge the bus, and send
2688507c3241Smlf * ATAPI DEVICE RESET to each ATAPI drive.
2689507c3241Smlf */
2690507c3241Smlf fsm_func = ATA_FSM_RESET;
2691507c3241Smlf for (watchdog = ata_reset_bus_watchdog; watchdog > 0; watchdog--) {
2692507c3241Smlf switch (ata_ctlr_fsm(fsm_func, ata_ctlp, NULL, NULL,
26932df1fe9cSrandyf &DoneFlg)) {
2694507c3241Smlf case ATA_FSM_RC_OKAY:
2695507c3241Smlf rc = TRUE;
2696507c3241Smlf goto fsm_done;
2697507c3241Smlf
2698507c3241Smlf case ATA_FSM_RC_BUSY:
2699507c3241Smlf return (FALSE);
2700507c3241Smlf
2701507c3241Smlf case ATA_FSM_RC_INTR:
2702507c3241Smlf fsm_func = ATA_FSM_INTR;
2703507c3241Smlf rc = TRUE;
2704507c3241Smlf continue;
2705507c3241Smlf
2706507c3241Smlf case ATA_FSM_RC_FINI:
2707507c3241Smlf fsm_func = ATA_FSM_FINI;
2708507c3241Smlf rc = TRUE;
2709507c3241Smlf continue;
2710507c3241Smlf }
2711507c3241Smlf }
2712507c3241Smlf ADBG_WARN(("ata_reset_bus: watchdog\n"));
2713507c3241Smlf
2714507c3241Smlf fsm_done:
2715507c3241Smlf
2716507c3241Smlf /*
2717507c3241Smlf * Reinitialize the ATA drives
2718507c3241Smlf */
2719507c3241Smlf for (drive = 0; drive < ATA_MAXTARG; drive++) {
2720507c3241Smlf ata_drv_t *ata_drvp;
2721507c3241Smlf
2722507c3241Smlf if ((ata_drvp = CTL2DRV(ata_ctlp, drive, 0)) == NULL)
2723507c3241Smlf continue;
2724507c3241Smlf
2725507c3241Smlf if (ATAPIDRV(ata_drvp))
2726507c3241Smlf continue;
2727507c3241Smlf
2728507c3241Smlf /*
2729507c3241Smlf * Reprogram the Read/Write Multiple block factor
2730507c3241Smlf * and current geometry into the drive.
2731507c3241Smlf */
2732507c3241Smlf if (!ata_disk_setup_parms(ata_ctlp, ata_drvp))
2733507c3241Smlf rc = FALSE;
2734507c3241Smlf }
2735507c3241Smlf
2736507c3241Smlf /* If DoneFlg is TRUE, it means that ghd_complete() function */
2737507c3241Smlf /* has been already called. In this case ignore any errors and */
2738507c3241Smlf /* return TRUE to the caller, otherwise return the value of rc */
2739507c3241Smlf /* to the caller */
2740507c3241Smlf if (DoneFlg)
2741507c3241Smlf return (TRUE);
2742507c3241Smlf else
2743507c3241Smlf return (rc);
2744507c3241Smlf }
2745507c3241Smlf
2746507c3241Smlf
2747507c3241Smlf /*
2748507c3241Smlf *
2749507c3241Smlf * Low level routine to toggle the Software Reset bit
2750507c3241Smlf *
2751507c3241Smlf */
2752507c3241Smlf
2753507c3241Smlf static int
ata_software_reset(ata_ctl_t * ata_ctlp)2754507c3241Smlf ata_software_reset(
2755507c3241Smlf ata_ctl_t *ata_ctlp)
2756507c3241Smlf {
2757507c3241Smlf ddi_acc_handle_t io_hdl1 = ata_ctlp->ac_iohandle1;
2758507c3241Smlf ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
27599f49ae27Smlf hrtime_t deadline;
27609f49ae27Smlf uint_t usecs_left;
2761507c3241Smlf
2762507c3241Smlf ADBG_TRACE(("ata_reset_bus entered\n"));
2763507c3241Smlf
2764507c3241Smlf /* disable interrupts and turn the software reset bit on */
2765507c3241Smlf ddi_put8(io_hdl2, ata_ctlp->ac_devctl, (ATDC_D3 | ATDC_SRST));
2766507c3241Smlf
2767507c3241Smlf /* why 30 milliseconds, the ATA/ATAPI-4 spec says 5 usec. */
2768507c3241Smlf drv_usecwait(30000);
2769507c3241Smlf
2770507c3241Smlf /* turn the software reset bit back off */
2771507c3241Smlf ddi_put8(io_hdl2, ata_ctlp->ac_devctl, ATDC_D3);
2772507c3241Smlf
2773507c3241Smlf /*
2774507c3241Smlf * Wait for the controller to assert BUSY status.
2775507c3241Smlf * I don't think 300 msecs is correct. The ATA/ATAPI-4
2776507c3241Smlf * spec says 400 nsecs, (and 2 msecs if device
2777507c3241Smlf * was in sleep mode; but we don't put drives to sleep
2778507c3241Smlf * so it probably doesn't matter).
2779507c3241Smlf */
2780507c3241Smlf drv_usecwait(300000);
2781507c3241Smlf
2782507c3241Smlf /*
2783507c3241Smlf * If drive 0 exists the test for completion is simple
2784507c3241Smlf */
27859f49ae27Smlf deadline = gethrtime() + ((hrtime_t)31 * NANOSEC);
27869f49ae27Smlf
2787507c3241Smlf if (CTL2DRV(ata_ctlp, 0, 0)) {
2788507c3241Smlf goto wait_for_not_busy;
2789507c3241Smlf }
2790507c3241Smlf
2791507c3241Smlf ASSERT(CTL2DRV(ata_ctlp, 1, 0) != NULL);
2792507c3241Smlf
2793507c3241Smlf /*
2794507c3241Smlf * This must be a single device configuration, with drive 1
2795507c3241Smlf * only. This complicates the test for completion because
2796507c3241Smlf * issuing the software reset just caused drive 1 to
2797507c3241Smlf * deselect. With drive 1 deselected, if I just read the
2798507c3241Smlf * status register to test the BSY bit I get garbage, but
2799507c3241Smlf * I can't re-select drive 1 until I'm certain the BSY bit
2800507c3241Smlf * is de-asserted. Catch-22.
2801507c3241Smlf *
2802507c3241Smlf * In ATA/ATAPI-4, rev 15, section 9.16.2, it says to handle
2803507c3241Smlf * this situation like this:
2804507c3241Smlf */
2805507c3241Smlf
2806507c3241Smlf /* give up if the drive doesn't settle within 31 seconds */
28079f49ae27Smlf while (gethrtime() < deadline) {
2808507c3241Smlf /*
2809507c3241Smlf * delay 10msec each time around the loop
2810507c3241Smlf */
2811507c3241Smlf drv_usecwait(10000);
2812507c3241Smlf
2813507c3241Smlf /*
2814507c3241Smlf * try to select drive 1
2815507c3241Smlf */
2816507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_drvhd, ATDH_DRIVE1);
2817507c3241Smlf
2818507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_sect, 0x55);
2819507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_sect, 0xaa);
2820507c3241Smlf if (ddi_get8(io_hdl1, ata_ctlp->ac_sect) != 0xaa)
2821507c3241Smlf continue;
2822507c3241Smlf
2823507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_count, 0x55);
2824507c3241Smlf ddi_put8(io_hdl1, ata_ctlp->ac_count, 0xaa);
2825507c3241Smlf if (ddi_get8(io_hdl1, ata_ctlp->ac_count) != 0xaa)
2826507c3241Smlf continue;
2827507c3241Smlf
2828507c3241Smlf goto wait_for_not_busy;
2829507c3241Smlf }
2830507c3241Smlf return (FALSE);
2831507c3241Smlf
2832507c3241Smlf wait_for_not_busy:
2833507c3241Smlf
2834507c3241Smlf /*
28359f49ae27Smlf * Now wait up to 31 seconds for BUSY to clear.
2836507c3241Smlf */
28379f49ae27Smlf usecs_left = (deadline - gethrtime()) / 1000;
2838507c3241Smlf (void) ata_wait3(io_hdl2, ata_ctlp->ac_ioaddr2, 0, ATS_BSY,
28392df1fe9cSrandyf ATS_ERR, ATS_BSY, ATS_DF, ATS_BSY, usecs_left);
2840507c3241Smlf
2841507c3241Smlf return (TRUE);
2842507c3241Smlf }
2843507c3241Smlf
2844507c3241Smlf /*
2845507c3241Smlf *
2846507c3241Smlf * DDI interrupt handler
2847507c3241Smlf *
2848507c3241Smlf */
2849507c3241Smlf
2850507c3241Smlf static uint_t
ata_intr(caddr_t arg)2851507c3241Smlf ata_intr(
2852507c3241Smlf caddr_t arg)
2853507c3241Smlf {
2854507c3241Smlf ata_ctl_t *ata_ctlp;
2855507c3241Smlf int one_shot = 1;
2856507c3241Smlf
2857507c3241Smlf ata_ctlp = (ata_ctl_t *)arg;
2858507c3241Smlf
2859507c3241Smlf return (ghd_intr(&ata_ctlp->ac_ccc, (void *)&one_shot));
2860507c3241Smlf }
2861507c3241Smlf
2862507c3241Smlf
2863507c3241Smlf /*
2864507c3241Smlf *
2865507c3241Smlf * GHD ccc_get_status callback
2866507c3241Smlf *
2867507c3241Smlf */
2868507c3241Smlf
2869507c3241Smlf static int
ata_get_status(void * hba_handle,void * intr_status)2870507c3241Smlf ata_get_status(
2871507c3241Smlf void *hba_handle,
2872507c3241Smlf void *intr_status)
2873507c3241Smlf {
2874507c3241Smlf ata_ctl_t *ata_ctlp = (ata_ctl_t *)hba_handle;
2875507c3241Smlf uchar_t status;
2876507c3241Smlf
2877507c3241Smlf ADBG_TRACE(("ata_get_status entered\n"));
2878507c3241Smlf
2879507c3241Smlf /*
2880507c3241Smlf * ignore interrupts before ata_attach completes
2881507c3241Smlf */
2882507c3241Smlf if (!(ata_ctlp->ac_flags & AC_ATTACHED))
2883507c3241Smlf return (FALSE);
2884507c3241Smlf
2885507c3241Smlf /*
2886507c3241Smlf * can't be interrupt pending if nothing active
2887507c3241Smlf */
2888507c3241Smlf switch (ata_ctlp->ac_state) {
2889507c3241Smlf case AS_IDLE:
2890507c3241Smlf return (FALSE);
2891507c3241Smlf case AS_ACTIVE0:
2892507c3241Smlf case AS_ACTIVE1:
2893507c3241Smlf ASSERT(ata_ctlp->ac_active_drvp != NULL);
2894507c3241Smlf ASSERT(ata_ctlp->ac_active_pktp != NULL);
2895507c3241Smlf break;
2896507c3241Smlf }
2897507c3241Smlf
2898507c3241Smlf /*
2899507c3241Smlf * If this is a PCI-IDE controller, check the PCI-IDE controller's
2900507c3241Smlf * interrupt status latch. But don't clear it yet.
2901507c3241Smlf *
2902507c3241Smlf * AC_BMSTATREG_PIO_BROKEN flag is used currently for
2903507c3241Smlf * CMD chips with device id 0x646. Since the interrupt bit on
2904507c3241Smlf * Bus master IDE register is not usable when in PIO mode,
2905507c3241Smlf * this chip is treated as a legacy device for interrupt
2906507c3241Smlf * indication. The following code for CMD
2907507c3241Smlf * chips may need to be revisited when we enable support for dma.
2908507c3241Smlf *
2909507c3241Smlf * CHANGE: DMA is not disabled for these devices. BM intr bit is
2910507c3241Smlf * checked only if there was DMA used or BM intr is useable on PIO,
2911507c3241Smlf * else treat it as before - as legacy device.
2912507c3241Smlf */
2913507c3241Smlf
2914507c3241Smlf if ((ata_ctlp->ac_pciide) &&
2915507c3241Smlf ((ata_ctlp->ac_pciide_bm != FALSE) &&
2916507c3241Smlf ((ata_ctlp->ac_active_pktp->ap_pciide_dma == TRUE) ||
2917507c3241Smlf !(ata_ctlp->ac_flags & AC_BMSTATREG_PIO_BROKEN)))) {
2918507c3241Smlf
2919507c3241Smlf if (!ata_pciide_status_pending(ata_ctlp))
2920507c3241Smlf return (FALSE);
2921507c3241Smlf } else {
2922507c3241Smlf /*
2923507c3241Smlf * Interrupts from legacy ATA/IDE controllers are
2924507c3241Smlf * edge-triggered but the dumb legacy ATA/IDE controllers
2925507c3241Smlf * and drives don't have an interrupt status bit.
2926507c3241Smlf *
2927507c3241Smlf * Use a one_shot variable to make sure we only return
2928507c3241Smlf * one status per interrupt.
2929507c3241Smlf */
2930507c3241Smlf if (intr_status != NULL) {
2931507c3241Smlf int *one_shot = (int *)intr_status;
2932507c3241Smlf
2933507c3241Smlf if (*one_shot == 1)
2934507c3241Smlf *one_shot = 0;
2935507c3241Smlf else
2936507c3241Smlf return (FALSE);
2937507c3241Smlf }
2938507c3241Smlf }
2939507c3241Smlf
2940507c3241Smlf /* check if device is still busy */
2941507c3241Smlf
2942507c3241Smlf status = ddi_get8(ata_ctlp->ac_iohandle2, ata_ctlp->ac_altstatus);
2943507c3241Smlf if (status & ATS_BSY)
2944507c3241Smlf return (FALSE);
2945507c3241Smlf return (TRUE);
2946507c3241Smlf }
2947507c3241Smlf
2948507c3241Smlf
2949507c3241Smlf /*
2950507c3241Smlf *
2951507c3241Smlf * get the current status and clear the IRQ
2952507c3241Smlf *
2953507c3241Smlf */
2954507c3241Smlf
2955507c3241Smlf int
ata_get_status_clear_intr(ata_ctl_t * ata_ctlp,ata_pkt_t * ata_pktp)2956507c3241Smlf ata_get_status_clear_intr(
2957507c3241Smlf ata_ctl_t *ata_ctlp,
2958507c3241Smlf ata_pkt_t *ata_pktp)
2959507c3241Smlf {
2960507c3241Smlf uchar_t status;
2961507c3241Smlf
2962507c3241Smlf /*
2963507c3241Smlf * Here's where we clear the PCI-IDE interrupt latch. If this
2964507c3241Smlf * request used DMA mode then we also have to check and clear
2965507c3241Smlf * the DMA error latch at the same time.
2966507c3241Smlf */
2967507c3241Smlf
2968507c3241Smlf if (ata_pktp->ap_pciide_dma) {
2969507c3241Smlf if (ata_pciide_status_dmacheck_clear(ata_ctlp))
2970507c3241Smlf ata_pktp->ap_flags |= AP_ERROR | AP_TRAN_ERROR;
2971507c3241Smlf } else if ((ata_ctlp->ac_pciide) &&
2972507c3241Smlf !(ata_ctlp->ac_flags & AC_BMSTATREG_PIO_BROKEN)) {
2973507c3241Smlf /*
2974507c3241Smlf * Some requests don't use DMA mode and therefore won't
2975507c3241Smlf * set the DMA error latch, but we still have to clear
2976507c3241Smlf * the interrupt latch.
2977507c3241Smlf * Controllers with broken BM intr in PIO mode do not go
2978507c3241Smlf * through this path.
2979507c3241Smlf */
2980507c3241Smlf (void) ata_pciide_status_clear(ata_ctlp);
2981507c3241Smlf }
2982507c3241Smlf
2983507c3241Smlf /*
2984507c3241Smlf * this clears the drive's interrupt
2985507c3241Smlf */
2986507c3241Smlf status = ddi_get8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_status);
2987507c3241Smlf ADBG_TRACE(("ata_get_status_clear_intr: 0x%x\n", status));
2988507c3241Smlf return (status);
2989507c3241Smlf }
2990507c3241Smlf
2991507c3241Smlf
2992507c3241Smlf
2993507c3241Smlf /*
2994507c3241Smlf *
2995507c3241Smlf * GHD interrupt handler
2996507c3241Smlf *
2997507c3241Smlf */
2998507c3241Smlf
2999507c3241Smlf /* ARGSUSED */
3000507c3241Smlf static void
ata_process_intr(void * hba_handle,void * intr_status)3001507c3241Smlf ata_process_intr(
3002507c3241Smlf void *hba_handle,
3003507c3241Smlf void *intr_status)
3004507c3241Smlf {
3005507c3241Smlf ata_ctl_t *ata_ctlp = (ata_ctl_t *)hba_handle;
3006507c3241Smlf int watchdog;
3007507c3241Smlf uchar_t fsm_func;
3008507c3241Smlf int rc;
3009507c3241Smlf
3010507c3241Smlf ADBG_TRACE(("ata_process_intr entered\n"));
3011507c3241Smlf
3012507c3241Smlf /*
3013507c3241Smlf * process the ATA or ATAPI interrupt
3014507c3241Smlf */
3015507c3241Smlf
3016507c3241Smlf fsm_func = ATA_FSM_INTR;
3017507c3241Smlf for (watchdog = ata_process_intr_watchdog; watchdog > 0; watchdog--) {
3018507c3241Smlf rc = ata_ctlr_fsm(fsm_func, ata_ctlp, NULL, NULL, NULL);
3019507c3241Smlf
3020507c3241Smlf switch (rc) {
3021507c3241Smlf case ATA_FSM_RC_OKAY:
3022507c3241Smlf return;
3023507c3241Smlf
3024507c3241Smlf case ATA_FSM_RC_BUSY: /* wait for the next interrupt */
3025507c3241Smlf return;
3026507c3241Smlf
3027507c3241Smlf case ATA_FSM_RC_INTR: /* re-invoke the FSM */
3028507c3241Smlf fsm_func = ATA_FSM_INTR;
3029507c3241Smlf break;
3030507c3241Smlf
3031507c3241Smlf case ATA_FSM_RC_FINI: /* move a request to done Q */
3032507c3241Smlf fsm_func = ATA_FSM_FINI;
3033507c3241Smlf break;
3034507c3241Smlf }
3035507c3241Smlf }
3036507c3241Smlf ADBG_WARN(("ata_process_intr: watchdog\n"));
3037507c3241Smlf }
3038507c3241Smlf
3039507c3241Smlf
3040507c3241Smlf
3041507c3241Smlf /*
3042507c3241Smlf *
3043507c3241Smlf * GHD ccc_hba_start callback
3044507c3241Smlf *
3045507c3241Smlf */
3046507c3241Smlf
3047507c3241Smlf static int
ata_hba_start(void * hba_handle,gcmd_t * gcmdp)3048507c3241Smlf ata_hba_start(
3049507c3241Smlf void *hba_handle,
3050507c3241Smlf gcmd_t *gcmdp)
3051507c3241Smlf {
3052507c3241Smlf ata_ctl_t *ata_ctlp;
3053507c3241Smlf ata_drv_t *ata_drvp;
3054507c3241Smlf ata_pkt_t *ata_pktp;
3055507c3241Smlf uchar_t fsm_func;
3056507c3241Smlf int request_started;
3057507c3241Smlf int watchdog;
3058507c3241Smlf
3059507c3241Smlf ADBG_TRACE(("ata_hba_start entered\n"));
3060507c3241Smlf
3061507c3241Smlf ata_ctlp = (ata_ctl_t *)hba_handle;
3062507c3241Smlf
3063507c3241Smlf if (ata_ctlp->ac_active_drvp != NULL) {
3064507c3241Smlf ADBG_WARN(("ata_hba_start drvp not null\n"));
3065507c3241Smlf return (FALSE);
3066507c3241Smlf }
3067507c3241Smlf if (ata_ctlp->ac_active_pktp != NULL) {
3068507c3241Smlf ADBG_WARN(("ata_hba_start pktp not null\n"));
3069507c3241Smlf return (FALSE);
3070507c3241Smlf }
3071507c3241Smlf
3072507c3241Smlf ata_pktp = GCMD2APKT(gcmdp);
3073507c3241Smlf ata_drvp = GCMD2DRV(gcmdp);
3074507c3241Smlf
3075507c3241Smlf /*
3076507c3241Smlf * which drive?
3077507c3241Smlf */
3078507c3241Smlf if (ata_drvp->ad_targ == 0)
3079507c3241Smlf fsm_func = ATA_FSM_START0;
3080507c3241Smlf else
3081507c3241Smlf fsm_func = ATA_FSM_START1;
3082507c3241Smlf
3083507c3241Smlf /*
3084507c3241Smlf * start the request
3085507c3241Smlf */
3086507c3241Smlf request_started = FALSE;
3087507c3241Smlf for (watchdog = ata_hba_start_watchdog; watchdog > 0; watchdog--) {
3088507c3241Smlf switch (ata_ctlr_fsm(fsm_func, ata_ctlp, ata_drvp, ata_pktp,
30892df1fe9cSrandyf NULL)) {
3090507c3241Smlf case ATA_FSM_RC_OKAY:
3091507c3241Smlf request_started = TRUE;
3092507c3241Smlf goto fsm_done;
3093507c3241Smlf
3094507c3241Smlf case ATA_FSM_RC_BUSY:
3095507c3241Smlf /* if first time, tell GHD to requeue the request */
3096507c3241Smlf goto fsm_done;
3097507c3241Smlf
3098507c3241Smlf case ATA_FSM_RC_INTR:
3099507c3241Smlf /*
3100507c3241Smlf * The start function polled for the next
3101507c3241Smlf * bus phase, now fake an interrupt to process
3102507c3241Smlf * the next action.
3103507c3241Smlf */
3104507c3241Smlf request_started = TRUE;
3105507c3241Smlf fsm_func = ATA_FSM_INTR;
3106507c3241Smlf ata_drvp = NULL;
3107507c3241Smlf ata_pktp = NULL;
3108507c3241Smlf break;
3109507c3241Smlf
3110507c3241Smlf case ATA_FSM_RC_FINI: /* move request to the done queue */
3111507c3241Smlf request_started = TRUE;
3112507c3241Smlf fsm_func = ATA_FSM_FINI;
3113507c3241Smlf ata_drvp = NULL;
3114507c3241Smlf ata_pktp = NULL;
3115507c3241Smlf break;
3116507c3241Smlf }
3117507c3241Smlf }
3118507c3241Smlf ADBG_WARN(("ata_hba_start: watchdog\n"));
3119507c3241Smlf
3120507c3241Smlf fsm_done:
3121507c3241Smlf return (request_started);
3122507c3241Smlf
3123507c3241Smlf }
3124507c3241Smlf
3125507c3241Smlf static int
ata_check_pciide_blacklist(dev_info_t * dip,uint_t flags)3126507c3241Smlf ata_check_pciide_blacklist(
3127507c3241Smlf dev_info_t *dip,
3128507c3241Smlf uint_t flags)
3129507c3241Smlf {
3130507c3241Smlf ushort_t vendorid;
3131507c3241Smlf ushort_t deviceid;
3132507c3241Smlf pcibl_t *blp;
3133507c3241Smlf int *propp;
3134507c3241Smlf uint_t count;
3135507c3241Smlf int rc;
3136507c3241Smlf
3137507c3241Smlf
3138507c3241Smlf vendorid = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip),
31392df1fe9cSrandyf DDI_PROP_DONTPASS, "vendor-id", 0);
3140507c3241Smlf deviceid = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip),
31412df1fe9cSrandyf DDI_PROP_DONTPASS, "device-id", 0);
3142507c3241Smlf
3143507c3241Smlf /*
3144507c3241Smlf * first check for a match in the "pci-ide-blacklist" property
3145507c3241Smlf */
3146507c3241Smlf rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0,
31472df1fe9cSrandyf "pci-ide-blacklist", &propp, &count);
3148507c3241Smlf
3149507c3241Smlf if (rc == DDI_PROP_SUCCESS) {
3150507c3241Smlf count = (count * sizeof (uint_t)) / sizeof (pcibl_t);
3151507c3241Smlf blp = (pcibl_t *)propp;
3152507c3241Smlf while (count--) {
3153507c3241Smlf /* check for matching ID */
3154507c3241Smlf if ((vendorid & blp->b_vmask)
31552df1fe9cSrandyf != (blp->b_vendorid & blp->b_vmask)) {
3156507c3241Smlf blp++;
3157507c3241Smlf continue;
3158507c3241Smlf }
3159507c3241Smlf if ((deviceid & blp->b_dmask)
31602df1fe9cSrandyf != (blp->b_deviceid & blp->b_dmask)) {
3161507c3241Smlf blp++;
3162507c3241Smlf continue;
3163507c3241Smlf }
3164507c3241Smlf
3165507c3241Smlf /* got a match */
3166507c3241Smlf if (blp->b_flags & flags) {
3167507c3241Smlf ddi_prop_free(propp);
3168507c3241Smlf return (TRUE);
3169507c3241Smlf } else {
3170507c3241Smlf ddi_prop_free(propp);
3171507c3241Smlf return (FALSE);
3172507c3241Smlf }
3173507c3241Smlf }
3174507c3241Smlf ddi_prop_free(propp);
3175507c3241Smlf }
3176507c3241Smlf
3177507c3241Smlf /*
3178507c3241Smlf * then check the built-in blacklist
3179507c3241Smlf */
3180507c3241Smlf for (blp = ata_pciide_blacklist; blp->b_vendorid; blp++) {
3181507c3241Smlf if ((vendorid & blp->b_vmask) != blp->b_vendorid)
3182507c3241Smlf continue;
3183507c3241Smlf if ((deviceid & blp->b_dmask) != blp->b_deviceid)
3184507c3241Smlf continue;
3185507c3241Smlf if (!(blp->b_flags & flags))
3186507c3241Smlf continue;
3187507c3241Smlf return (TRUE);
3188507c3241Smlf }
3189507c3241Smlf return (FALSE);
3190507c3241Smlf }
3191507c3241Smlf
3192507c3241Smlf int
ata_check_drive_blacklist(struct ata_id * aidp,uint_t flags)3193507c3241Smlf ata_check_drive_blacklist(
3194507c3241Smlf struct ata_id *aidp,
3195507c3241Smlf uint_t flags)
3196507c3241Smlf {
3197507c3241Smlf atabl_t *blp;
3198507c3241Smlf
3199744a0601SLing Albert Ke for (blp = ata_drive_blacklist; blp->b_model != NULL; blp++) {
3200507c3241Smlf if (!ata_strncmp(blp->b_model, aidp->ai_model,
32012df1fe9cSrandyf sizeof (aidp->ai_model)))
3202507c3241Smlf continue;
3203744a0601SLing Albert Ke if (blp->b_fw != NULL) {
3204744a0601SLing Albert Ke if (!ata_strncmp(blp->b_fw, aidp->ai_fw,
3205744a0601SLing Albert Ke sizeof (aidp->ai_fw)))
3206744a0601SLing Albert Ke continue;
3207744a0601SLing Albert Ke }
3208507c3241Smlf if (blp->b_flags & flags)
3209507c3241Smlf return (TRUE);
3210507c3241Smlf return (FALSE);
3211507c3241Smlf }
3212507c3241Smlf return (FALSE);
3213507c3241Smlf }
3214507c3241Smlf
3215507c3241Smlf /*
3216507c3241Smlf * Queue a request to perform some sort of internally
3217507c3241Smlf * generated command. When this request packet reaches
3218507c3241Smlf * the front of the queue (*func)() is invoked.
3219507c3241Smlf *
3220507c3241Smlf */
3221507c3241Smlf
3222507c3241Smlf int
ata_queue_cmd(int (* func)(ata_ctl_t *,ata_drv_t *,ata_pkt_t *),void * arg,ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp,gtgt_t * gtgtp)3223507c3241Smlf ata_queue_cmd(
3224507c3241Smlf int (*func)(ata_ctl_t *, ata_drv_t *, ata_pkt_t *),
3225507c3241Smlf void *arg,
3226507c3241Smlf ata_ctl_t *ata_ctlp,
3227507c3241Smlf ata_drv_t *ata_drvp,
3228507c3241Smlf gtgt_t *gtgtp)
3229507c3241Smlf {
3230507c3241Smlf ata_pkt_t *ata_pktp;
3231507c3241Smlf gcmd_t *gcmdp;
3232507c3241Smlf int rc;
3233507c3241Smlf
3234507c3241Smlf if (!(gcmdp = ghd_gcmd_alloc(gtgtp, sizeof (*ata_pktp), TRUE))) {
3235507c3241Smlf ADBG_ERROR(("atapi_id_update alloc failed\n"));
3236507c3241Smlf return (FALSE);
3237507c3241Smlf }
3238507c3241Smlf
3239507c3241Smlf
3240507c3241Smlf /* set the back ptr from the ata_pkt to the gcmd_t */
3241507c3241Smlf ata_pktp = GCMD2APKT(gcmdp);
3242507c3241Smlf ata_pktp->ap_gcmdp = gcmdp;
3243507c3241Smlf ata_pktp->ap_hd = ata_drvp->ad_drive_bits;
3244507c3241Smlf ata_pktp->ap_bytes_per_block = ata_drvp->ad_bytes_per_block;
3245507c3241Smlf
3246507c3241Smlf /*
3247507c3241Smlf * over-ride the default start function
3248507c3241Smlf */
3249507c3241Smlf ata_pktp = GCMD2APKT(gcmdp);
3250507c3241Smlf ata_pktp->ap_start = func;
3251507c3241Smlf ata_pktp->ap_complete = NULL;
3252507c3241Smlf ata_pktp->ap_v_addr = (caddr_t)arg;
3253507c3241Smlf
3254507c3241Smlf /*
3255507c3241Smlf * add it to the queue, when it gets to the front the
3256507c3241Smlf * ap_start function is called.
3257507c3241Smlf */
3258507c3241Smlf rc = ghd_transport(&ata_ctlp->ac_ccc, gcmdp, gcmdp->cmd_gtgtp,
32592df1fe9cSrandyf 0, TRUE, NULL);
3260507c3241Smlf
3261507c3241Smlf if (rc != TRAN_ACCEPT) {
3262507c3241Smlf /* this should never, ever happen */
3263507c3241Smlf return (FALSE);
3264507c3241Smlf }
3265507c3241Smlf
3266507c3241Smlf if (ata_pktp->ap_flags & AP_ERROR)
3267507c3241Smlf return (FALSE);
3268507c3241Smlf return (TRUE);
3269507c3241Smlf }
3270507c3241Smlf
3271507c3241Smlf /*
3272507c3241Smlf * Check if this drive has the "revert to defaults" bug
3273507c3241Smlf * PSARC 2001/500 and 2001/xxx - check for the properties
3274507c3241Smlf * ata-revert-to-defaults and atarvrt-<diskmodel> before
3275507c3241Smlf * examining the blacklist.
3276507c3241Smlf * <diskmodel> is made from the model number reported by Identify Drive
3277507c3241Smlf * with uppercase letters converted to lowercase and all characters
3278507c3241Smlf * except letters, digits, ".", "_", and "-" deleted.
3279507c3241Smlf * Return value:
3280507c3241Smlf * TRUE: enable revert to defaults
3281507c3241Smlf * FALSE: disable revert to defaults
3282507c3241Smlf *
3283507c3241Smlf * NOTE: revert to power on defaults that includes reverting to MDMA
3284507c3241Smlf * mode is allowed by ATA-6 & ATA-7 specs.
3285507c3241Smlf * Therefore drives exhibiting this behaviour are not violating the spec.
3286507c3241Smlf * Furthermore, the spec explicitly says that after the soft reset
3287507c3241Smlf * host should check the current setting of the device features.
3288507c3241Smlf * Correctly working BIOS would therefore reprogram either the drive
3289507c3241Smlf * and/or the host controller to match transfer modes.
3290507c3241Smlf * Devices with ATA_BL_NORVRT flag will be removed from
3291507c3241Smlf * the ata_blacklist.
3292507c3241Smlf * The default behaviour will be - no revert to power-on defaults
3293507c3241Smlf * for all devices. The property is retained in case the user
3294507c3241Smlf * explicitly requests revert-to-defaults before reboot.
3295507c3241Smlf */
3296507c3241Smlf
3297507c3241Smlf #define ATA_REVERT_PROP_PREFIX "revert-"
3298507c3241Smlf #define ATA_REVERT_PROP_GLOBAL "ata-revert-to-defaults"
3299507c3241Smlf /* room for prefix + model number + terminating NUL character */
3300507c3241Smlf #define PROP_BUF_SIZE (sizeof (ATA_REVERT_PROP_PREFIX) + \
3301507c3241Smlf sizeof (aidp->ai_model) + 1)
3302507c3241Smlf #define PROP_LEN_MAX (31)
3303507c3241Smlf
3304507c3241Smlf static int
ata_check_revert_to_defaults(ata_drv_t * ata_drvp)3305507c3241Smlf ata_check_revert_to_defaults(
3306507c3241Smlf ata_drv_t *ata_drvp)
3307507c3241Smlf {
3308507c3241Smlf struct ata_id *aidp = &ata_drvp->ad_id;
3309507c3241Smlf ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
3310507c3241Smlf char prop_buf[PROP_BUF_SIZE];
3311507c3241Smlf int i, j;
3312507c3241Smlf int propval;
3313507c3241Smlf
3314507c3241Smlf /* put prefix into the buffer */
3315507c3241Smlf (void) strcpy(prop_buf, ATA_REVERT_PROP_PREFIX);
3316507c3241Smlf j = strlen(prop_buf);
3317507c3241Smlf
3318507c3241Smlf /* append the model number, leaving out invalid characters */
3319507c3241Smlf for (i = 0; i < sizeof (aidp->ai_model); ++i) {
3320507c3241Smlf char c = aidp->ai_model[i];
3321507c3241Smlf if (c >= 'A' && c <= 'Z') /* uppercase -> lower */
3322507c3241Smlf c = c - 'A' + 'a';
3323507c3241Smlf if (c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ||
3324507c3241Smlf c == '.' || c == '_' || c == '-')
3325507c3241Smlf prop_buf[j++] = c;
3326507c3241Smlf if (c == '\0')
3327507c3241Smlf break;
3328507c3241Smlf }
3329507c3241Smlf
3330507c3241Smlf /* make sure there's a terminating NUL character */
3331507c3241Smlf if (j >= PROP_LEN_MAX)
3332507c3241Smlf j = PROP_LEN_MAX;
3333507c3241Smlf prop_buf[j] = '\0';
3334507c3241Smlf
3335507c3241Smlf /* look for a disk-specific "revert" property" */
3336507c3241Smlf propval = ddi_getprop(DDI_DEV_T_ANY, ata_ctlp->ac_dip,
33372df1fe9cSrandyf DDI_PROP_DONTPASS, prop_buf, -1);
3338507c3241Smlf if (propval == 0)
3339507c3241Smlf return (FALSE);
3340507c3241Smlf else if (propval != -1)
3341507c3241Smlf return (TRUE);
3342507c3241Smlf
3343507c3241Smlf /* look for a global "revert" property" */
3344507c3241Smlf propval = ddi_getprop(DDI_DEV_T_ANY, ata_ctlp->ac_dip,
33452df1fe9cSrandyf 0, ATA_REVERT_PROP_GLOBAL, -1);
3346507c3241Smlf if (propval == 0)
3347507c3241Smlf return (FALSE);
3348507c3241Smlf else if (propval != -1)
3349507c3241Smlf return (TRUE);
3350507c3241Smlf
3351507c3241Smlf return (FALSE);
3352507c3241Smlf }
3353507c3241Smlf
3354507c3241Smlf void
ata_show_transfer_mode(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp)3355507c3241Smlf ata_show_transfer_mode(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp)
3356507c3241Smlf {
3357507c3241Smlf int i;
3358507c3241Smlf
3359507c3241Smlf if (ata_ctlp->ac_pciide_bm == FALSE ||
3360507c3241Smlf ata_drvp->ad_pciide_dma != ATA_DMA_ON) {
3361507c3241Smlf if (ata_cntrl_DMA_sel_msg) {
3362507c3241Smlf ATAPRT((
3363507c3241Smlf "?\tATA DMA off: %s\n", ata_cntrl_DMA_sel_msg));
3364507c3241Smlf } else if (ata_dev_DMA_sel_msg) {
3365507c3241Smlf ATAPRT(("?\tATA DMA off: %s\n", ata_dev_DMA_sel_msg));
3366507c3241Smlf }
3367507c3241Smlf ATAPRT(("?\tPIO mode %d selected\n",
3368507c3241Smlf (ata_drvp->ad_id.ai_advpiomode & ATAC_ADVPIO_4_SUP) ==
33692df1fe9cSrandyf ATAC_ADVPIO_4_SUP ? 4 : 3));
3370507c3241Smlf } else {
3371507c3241Smlf /* Using DMA */
3372507c3241Smlf if (ata_drvp->ad_id.ai_dworddma & ATAC_MDMA_SEL_MASK) {
3373507c3241Smlf /*
3374507c3241Smlf * Rely on the fact that either dwdma or udma is
3375507c3241Smlf * selected, not both.
3376507c3241Smlf */
3377507c3241Smlf ATAPRT(("?\tMultiwordDMA mode %d selected\n",
33782df1fe9cSrandyf (ata_drvp->ad_id.ai_dworddma & ATAC_MDMA_2_SEL) ==
3379507c3241Smlf ATAC_MDMA_2_SEL ? 2 :
3380507c3241Smlf (ata_drvp->ad_id.ai_dworddma & ATAC_MDMA_1_SEL) ==
33812df1fe9cSrandyf ATAC_MDMA_1_SEL ? 1 : 0));
3382507c3241Smlf } else {
3383507c3241Smlf for (i = 0; i <= 6; i++) {
3384507c3241Smlf if (ata_drvp->ad_id.ai_ultradma &
3385507c3241Smlf (1 << (i + 8))) {
3386507c3241Smlf ATAPRT((
3387507c3241Smlf "?\tUltraDMA mode %d selected\n",
3388507c3241Smlf i));
3389507c3241Smlf break;
3390507c3241Smlf }
3391507c3241Smlf }
3392507c3241Smlf }
3393507c3241Smlf }
3394507c3241Smlf }
3395507c3241Smlf
3396507c3241Smlf /*
3397507c3241Smlf * Controller-specific operation pointers.
3398507c3241Smlf * Should be extended as needed - init only for now
3399507c3241Smlf */
3400507c3241Smlf struct ata_ctl_spec_ops {
3401507c3241Smlf uint_t (*cs_init)(dev_info_t *, ushort_t, ushort_t); /* ctlr init */
3402507c3241Smlf };
3403507c3241Smlf
3404507c3241Smlf
3405507c3241Smlf struct ata_ctl_spec {
3406507c3241Smlf ushort_t cs_vendor_id;
3407507c3241Smlf ushort_t cs_device_id;
3408507c3241Smlf struct ata_ctl_spec_ops *cs_ops;
3409507c3241Smlf };
3410507c3241Smlf
3411507c3241Smlf /* Sil3XXX-specific functions (init only for now) */
3412507c3241Smlf struct ata_ctl_spec_ops sil3xxx_ops = {
3413507c3241Smlf &sil3xxx_init_controller /* Sil3XXX cntrl initialization */
3414507c3241Smlf };
3415507c3241Smlf
3416507c3241Smlf
3417507c3241Smlf struct ata_ctl_spec ata_cntrls_spec[] = {
3418507c3241Smlf {0x1095, 0x3114, &sil3xxx_ops},
3419507c3241Smlf {0x1095, 0x3512, &sil3xxx_ops},
3420507c3241Smlf {0x1095, 0x3112, &sil3xxx_ops},
3421507c3241Smlf {0, 0, NULL} /* List must end with cs_ops set to NULL */
3422507c3241Smlf };
3423507c3241Smlf
3424507c3241Smlf /*
3425507c3241Smlf * Do controller specific initialization if necessary.
3426507c3241Smlf * Pick-up controller specific functions.
3427507c3241Smlf */
3428507c3241Smlf
3429507c3241Smlf int
ata_spec_init_controller(dev_info_t * dip)3430507c3241Smlf ata_spec_init_controller(dev_info_t *dip)
3431507c3241Smlf {
3432507c3241Smlf ushort_t vendor_id;
3433507c3241Smlf ushort_t device_id;
3434507c3241Smlf struct ata_ctl_spec *ctlsp;
3435507c3241Smlf
3436507c3241Smlf vendor_id = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip),
34372df1fe9cSrandyf DDI_PROP_DONTPASS, "vendor-id", 0);
3438507c3241Smlf device_id = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip),
34392df1fe9cSrandyf DDI_PROP_DONTPASS, "device-id", 0);
3440507c3241Smlf
3441507c3241Smlf /* Locate controller specific ops, if they exist */
3442507c3241Smlf ctlsp = ata_cntrls_spec;
3443507c3241Smlf while (ctlsp->cs_ops != NULL) {
3444507c3241Smlf if (ctlsp->cs_vendor_id == vendor_id &&
3445507c3241Smlf ctlsp->cs_device_id == device_id)
3446507c3241Smlf break;
3447507c3241Smlf ctlsp++;
3448507c3241Smlf }
3449507c3241Smlf
3450507c3241Smlf if (ctlsp->cs_ops != NULL) {
3451507c3241Smlf if (ctlsp->cs_ops->cs_init != NULL) {
3452507c3241Smlf /* Initialize controller */
3453507c3241Smlf if ((*(ctlsp->cs_ops->cs_init))
3454507c3241Smlf (dip, vendor_id, device_id) != TRUE) {
3455507c3241Smlf cmn_err(CE_WARN,
3456507c3241Smlf "pci%4x,%4x cntrl specific "
3457507c3241Smlf "initialization failed",
3458507c3241Smlf vendor_id, device_id);
3459507c3241Smlf return (FALSE);
3460507c3241Smlf }
3461507c3241Smlf }
3462507c3241Smlf }
3463507c3241Smlf return (TRUE);
3464507c3241Smlf }
3465507c3241Smlf
3466507c3241Smlf /*
3467507c3241Smlf * this routine works like ddi_prop_get_int, except that it works on
3468507c3241Smlf * a string property that contains ascii representations
3469507c3241Smlf * of an integer.
3470507c3241Smlf * If the property is not found, the default value is returned.
3471507c3241Smlf */
3472507c3241Smlf static int
ata_prop_lookup_int(dev_t match_dev,dev_info_t * dip,uint_t flags,char * name,int defvalue)3473507c3241Smlf ata_prop_lookup_int(dev_t match_dev, dev_info_t *dip,
3474*6e6c7d67SAndrew Stormont uint_t flags, char *name, int defvalue)
3475507c3241Smlf {
3476507c3241Smlf
3477507c3241Smlf char *bufp, *cp;
3478507c3241Smlf int rc = defvalue;
3479507c3241Smlf int proprc;
3480507c3241Smlf
3481507c3241Smlf proprc = ddi_prop_lookup_string(match_dev, dip,
34822df1fe9cSrandyf flags, name, &bufp);
3483507c3241Smlf
3484507c3241Smlf if (proprc == DDI_PROP_SUCCESS) {
3485507c3241Smlf cp = bufp;
3486507c3241Smlf rc = stoi(&cp);
3487507c3241Smlf ddi_prop_free(bufp);
3488507c3241Smlf } else {
3489507c3241Smlf /*
3490507c3241Smlf * see if property is encoded as an int instead of string.
3491507c3241Smlf */
3492507c3241Smlf rc = ddi_prop_get_int(match_dev, dip, flags, name, defvalue);
3493507c3241Smlf }
3494507c3241Smlf
3495507c3241Smlf return (rc);
3496507c3241Smlf }
34972df1fe9cSrandyf
34982df1fe9cSrandyf /*
34992df1fe9cSrandyf * Initialize the power management components
35002df1fe9cSrandyf */
35012df1fe9cSrandyf static void
ata_init_pm(dev_info_t * dip)35022df1fe9cSrandyf ata_init_pm(dev_info_t *dip)
35032df1fe9cSrandyf {
3504*6e6c7d67SAndrew Stormont int instance;
3505*6e6c7d67SAndrew Stormont ata_ctl_t *ata_ctlp;
3506*6e6c7d67SAndrew Stormont #ifdef ATA_USE_AUTOPM
35072df1fe9cSrandyf char pmc_name[16];
35082df1fe9cSrandyf char *pmc[] = {
35092df1fe9cSrandyf NULL,
35102df1fe9cSrandyf "0=Sleep (PCI D3 State)",
35112df1fe9cSrandyf "3=PowerOn (PCI D0 State)",
35122df1fe9cSrandyf NULL
35132df1fe9cSrandyf };
3514*6e6c7d67SAndrew Stormont #endif
35152df1fe9cSrandyf
35162df1fe9cSrandyf
35172df1fe9cSrandyf instance = ddi_get_instance(dip);
35182df1fe9cSrandyf ata_ctlp = ddi_get_soft_state(ata_state, instance);
35192df1fe9cSrandyf ata_ctlp->ac_pm_support = 0;
35202df1fe9cSrandyf
35212df1fe9cSrandyf /* check PCI capabilities */
35222df1fe9cSrandyf if (!ata_is_pci(dip))
35232df1fe9cSrandyf return;
35242df1fe9cSrandyf
3525*6e6c7d67SAndrew Stormont #ifdef ATA_USE_AUTOPM
35262df1fe9cSrandyf (void) sprintf(pmc_name, "NAME=ata%d", instance);
35272df1fe9cSrandyf pmc[0] = pmc_name;
35282df1fe9cSrandyf
35292df1fe9cSrandyf if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
35302df1fe9cSrandyf "pm-components", pmc, 3) != DDI_PROP_SUCCESS) {
35312df1fe9cSrandyf return;
35322df1fe9cSrandyf }
35332df1fe9cSrandyf #endif
35342df1fe9cSrandyf
35352df1fe9cSrandyf ata_ctlp->ac_pm_support = 1;
35362df1fe9cSrandyf ata_ctlp->ac_pm_level = PM_LEVEL_D0;
35372df1fe9cSrandyf
35382df1fe9cSrandyf ATA_BUSY_COMPONENT(dip, 0);
35392df1fe9cSrandyf if (ATA_RAISE_POWER(dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) {
35402df1fe9cSrandyf (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-components");
35412df1fe9cSrandyf }
35422df1fe9cSrandyf ATA_IDLE_COMPONENT(dip, 0);
35432df1fe9cSrandyf }
35442df1fe9cSrandyf
35452df1fe9cSrandyf /*
35462df1fe9cSrandyf * resume the hard drive
35472df1fe9cSrandyf */
35482df1fe9cSrandyf static void
ata_resume_drive(ata_drv_t * ata_drvp)35492df1fe9cSrandyf ata_resume_drive(ata_drv_t *ata_drvp)
35502df1fe9cSrandyf {
35512df1fe9cSrandyf ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
35522df1fe9cSrandyf int drive_type;
35532df1fe9cSrandyf struct ata_id id;
35542df1fe9cSrandyf
35552df1fe9cSrandyf ADBG_TRACE(("ata_resume_drive entered\n"));
35562df1fe9cSrandyf
35572df1fe9cSrandyf drive_type = ata_drive_type(ata_drvp->ad_drive_bits,
35582df1fe9cSrandyf ata_ctlp->ac_iohandle1, ata_ctlp->ac_ioaddr1,
35592df1fe9cSrandyf ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2,
35602df1fe9cSrandyf &id);
35612df1fe9cSrandyf if (drive_type == ATA_DEV_NONE)
35622df1fe9cSrandyf return;
35632df1fe9cSrandyf
35642df1fe9cSrandyf if (!ATAPIDRV(ata_drvp)) {
356562c8caf3SAda /* Reset Ultra DMA mode */
35660f1b305eSSeth Goldberg ata_reset_dma_mode(ata_drvp);
35672df1fe9cSrandyf if (!ata_disk_setup_parms(ata_ctlp, ata_drvp))
35682df1fe9cSrandyf return;
356962c8caf3SAda } else {
3570b44e05abSAda (void) atapi_init_drive(ata_drvp);
3571fe072f42SAda if (ata_drvp->ad_dma_mode != 0) {
3572fe072f42SAda (void) atapi_reset_dma_mode(ata_drvp, FALSE);
3573fe072f42SAda if (!ata_check_dma_mode(ata_drvp))
3574fe072f42SAda atapi_reset_dma_mode(ata_drvp, TRUE);
3575fe072f42SAda if (ata_drvp->ad_id.ai_ultradma !=
3576fe072f42SAda ata_drvp->ad_dma_mode) {
3577fe072f42SAda ata_drvp->ad_pciide_dma = ATA_DMA_OFF;
3578fe072f42SAda } else {
3579fe072f42SAda ata_drvp->ad_pciide_dma = ATA_DMA_ON;
3580fe072f42SAda }
3581fe072f42SAda }
35822df1fe9cSrandyf }
358362c8caf3SAda (void) ata_set_feature(ata_ctlp, ata_drvp, ATSF_DIS_REVPOD, 0);
358462c8caf3SAda
35852df1fe9cSrandyf }
35862df1fe9cSrandyf
35872df1fe9cSrandyf /*
35882df1fe9cSrandyf * resume routine, it will be run when get the command
35892df1fe9cSrandyf * DDI_RESUME at attach(9E) from system power management
35902df1fe9cSrandyf */
35912df1fe9cSrandyf static int
ata_resume(dev_info_t * dip)35922df1fe9cSrandyf ata_resume(dev_info_t *dip)
35932df1fe9cSrandyf {
35942df1fe9cSrandyf int instance;
35952df1fe9cSrandyf ata_ctl_t *ata_ctlp;
35962df1fe9cSrandyf ddi_acc_handle_t io_hdl2;
35972df1fe9cSrandyf caddr_t ioaddr2;
35982df1fe9cSrandyf
35992df1fe9cSrandyf instance = ddi_get_instance(dip);
36002df1fe9cSrandyf ata_ctlp = ddi_get_soft_state(ata_state, instance);
36012df1fe9cSrandyf
36022df1fe9cSrandyf if (!ata_ctlp->ac_pm_support)
36032df1fe9cSrandyf return (DDI_FAILURE);
36042df1fe9cSrandyf if (ata_ctlp->ac_pm_level == PM_LEVEL_D0)
36052df1fe9cSrandyf return (DDI_SUCCESS);
36062df1fe9cSrandyf
36072df1fe9cSrandyf ATA_BUSY_COMPONENT(dip, 0);
36082df1fe9cSrandyf if (ATA_RAISE_POWER(dip, 0, PM_LEVEL_D0) == DDI_FAILURE)
36092df1fe9cSrandyf return (DDI_FAILURE);
36102df1fe9cSrandyf ATA_IDLE_COMPONENT(dip, 0);
36112df1fe9cSrandyf
36122df1fe9cSrandyf /* enable interrupts from the device */
36132df1fe9cSrandyf io_hdl2 = ata_ctlp->ac_iohandle2;
36142df1fe9cSrandyf ioaddr2 = ata_ctlp->ac_ioaddr2;
36152df1fe9cSrandyf ddi_put8(io_hdl2, (uchar_t *)ioaddr2 + AT_DEVCTL, ATDC_D3);
36162df1fe9cSrandyf ata_ctlp->ac_pm_level = PM_LEVEL_D0;
36172df1fe9cSrandyf
36182df1fe9cSrandyf return (DDI_SUCCESS);
36192df1fe9cSrandyf }
36202df1fe9cSrandyf
36212df1fe9cSrandyf /*
36222df1fe9cSrandyf * suspend routine, it will be run when get the command
36232df1fe9cSrandyf * DDI_SUSPEND at detach(9E) from system power management
36242df1fe9cSrandyf */
36252df1fe9cSrandyf static int
ata_suspend(dev_info_t * dip)36262df1fe9cSrandyf ata_suspend(dev_info_t *dip)
36272df1fe9cSrandyf {
36282df1fe9cSrandyf int instance;
36292df1fe9cSrandyf ata_ctl_t *ata_ctlp;
36302df1fe9cSrandyf ddi_acc_handle_t io_hdl2;
36312df1fe9cSrandyf
36322df1fe9cSrandyf instance = ddi_get_instance(dip);
36332df1fe9cSrandyf ata_ctlp = ddi_get_soft_state(ata_state, instance);
36342df1fe9cSrandyf
36352df1fe9cSrandyf if (!ata_ctlp->ac_pm_support)
36362df1fe9cSrandyf return (DDI_FAILURE);
36372df1fe9cSrandyf if (ata_ctlp->ac_pm_level == PM_LEVEL_D3)
36382df1fe9cSrandyf return (DDI_SUCCESS);
36392df1fe9cSrandyf
36402df1fe9cSrandyf /* disable interrupts and turn the software reset bit on */
36412df1fe9cSrandyf io_hdl2 = ata_ctlp->ac_iohandle2;
36422df1fe9cSrandyf ddi_put8(io_hdl2, ata_ctlp->ac_devctl, (ATDC_D3 | ATDC_SRST));
36432df1fe9cSrandyf
36442df1fe9cSrandyf (void) ata_reset_bus(ata_ctlp);
36452df1fe9cSrandyf (void) ata_change_power(dip, ATC_SLEEP);
36462df1fe9cSrandyf ata_ctlp->ac_pm_level = PM_LEVEL_D3;
36472df1fe9cSrandyf return (DDI_SUCCESS);
36482df1fe9cSrandyf }
36492df1fe9cSrandyf
36502df1fe9cSrandyf int ata_save_pci_config = 0;
36512df1fe9cSrandyf /*
36522df1fe9cSrandyf * ata specific power management entry point, it was
36532df1fe9cSrandyf * used to change the power management component
36542df1fe9cSrandyf */
36552df1fe9cSrandyf static int
ata_power(dev_info_t * dip,int component,int level)36562df1fe9cSrandyf ata_power(dev_info_t *dip, int component, int level)
36572df1fe9cSrandyf {
36582df1fe9cSrandyf int instance;
36592df1fe9cSrandyf ata_ctl_t *ata_ctlp;
36602df1fe9cSrandyf uint8_t cmd;
36612df1fe9cSrandyf
36622df1fe9cSrandyf ADBG_TRACE(("ata_power entered, component = %d, level = %d\n",
36632df1fe9cSrandyf component, level));
36642df1fe9cSrandyf
36652df1fe9cSrandyf instance = ddi_get_instance(dip);
36662df1fe9cSrandyf ata_ctlp = ddi_get_soft_state(ata_state, instance);
36672df1fe9cSrandyf if (ata_ctlp == NULL || component != 0)
36682df1fe9cSrandyf return (DDI_FAILURE);
36692df1fe9cSrandyf
36702df1fe9cSrandyf if (!ata_ctlp->ac_pm_support)
36712df1fe9cSrandyf return (DDI_FAILURE);
36722df1fe9cSrandyf
36738c97a06bSAda if (ata_ctlp->ac_pm_level == level)
36748c97a06bSAda return (DDI_SUCCESS);
36758c97a06bSAda
36762df1fe9cSrandyf switch (level) {
36772df1fe9cSrandyf case PM_LEVEL_D0:
36782df1fe9cSrandyf if (ata_save_pci_config)
36792df1fe9cSrandyf (void) pci_restore_config_regs(dip);
36802df1fe9cSrandyf ata_ctlp->ac_pm_level = PM_LEVEL_D0;
3681dcafa541Srandyf cmd = ATC_IDLE_IMMED;
36822df1fe9cSrandyf break;
36832df1fe9cSrandyf case PM_LEVEL_D3:
36842df1fe9cSrandyf if (ata_save_pci_config)
36852df1fe9cSrandyf (void) pci_save_config_regs(dip);
36862df1fe9cSrandyf ata_ctlp->ac_pm_level = PM_LEVEL_D3;
36872df1fe9cSrandyf cmd = ATC_SLEEP;
36882df1fe9cSrandyf break;
36892df1fe9cSrandyf default:
36902df1fe9cSrandyf return (DDI_FAILURE);
36912df1fe9cSrandyf }
36922df1fe9cSrandyf return (ata_change_power(dip, cmd));
36932df1fe9cSrandyf }
36942df1fe9cSrandyf
36952df1fe9cSrandyf /*
36962df1fe9cSrandyf * sent commands to ata controller to change the power level
36972df1fe9cSrandyf */
36982df1fe9cSrandyf static int
ata_change_power(dev_info_t * dip,uint8_t cmd)36992df1fe9cSrandyf ata_change_power(dev_info_t *dip, uint8_t cmd)
37002df1fe9cSrandyf {
37012df1fe9cSrandyf int instance;
3702fe072f42SAda ata_ctl_t *ata_ctlp;
37032df1fe9cSrandyf ata_drv_t *ata_drvp;
37042df1fe9cSrandyf uchar_t targ;
3705fe072f42SAda struct ata_id id;
37062df1fe9cSrandyf uchar_t lun;
37072df1fe9cSrandyf uchar_t lastlun;
37088c97a06bSAda struct ata_id *aidp;
37092df1fe9cSrandyf
37102df1fe9cSrandyf ADBG_TRACE(("ata_change_power entered, cmd = %d\n", cmd));
37112df1fe9cSrandyf
37122df1fe9cSrandyf instance = ddi_get_instance(dip);
37132df1fe9cSrandyf ata_ctlp = ddi_get_soft_state(ata_state, instance);
37148c97a06bSAda
37152df1fe9cSrandyf /*
37162df1fe9cSrandyf * Issue command on each disk device on the bus.
37172df1fe9cSrandyf */
371862c8caf3SAda if (cmd == ATC_SLEEP) {
371962c8caf3SAda for (targ = 0; targ < ATA_MAXTARG; targ++) {
372062c8caf3SAda ata_drvp = CTL2DRV(ata_ctlp, targ, 0);
372162c8caf3SAda if (ata_drvp == NULL)
372262c8caf3SAda continue;
3723fe072f42SAda if (ata_drvp->ad_dma_cap == 0 &&
3724fe072f42SAda ata_drvp->ad_pciide_dma == ATA_DMA_ON) {
3725fe072f42SAda aidp = &ata_drvp->ad_id;
3726fe072f42SAda if ((aidp->ai_validinfo & ATAC_VALIDINFO_83) &&
3727fe072f42SAda (aidp->ai_ultradma & ATAC_UDMA_SEL_MASK)) {
3728fe072f42SAda ata_drvp->ad_dma_cap =
3729fe072f42SAda ATA_DMA_ULTRAMODE;
3730fe072f42SAda ata_drvp->ad_dma_mode =
3731fe072f42SAda aidp->ai_ultradma;
3732fe072f42SAda } else if (aidp->ai_dworddma &
3733fe072f42SAda ATAC_MDMA_SEL_MASK) {
3734fe072f42SAda ata_drvp->ad_dma_cap =
3735fe072f42SAda ATA_DMA_MWORDMODE;
3736fe072f42SAda ata_drvp->ad_dma_mode =
3737fe072f42SAda aidp->ai_dworddma;
3738fe072f42SAda }
37398c97a06bSAda }
374062c8caf3SAda if (ata_drive_type(ata_drvp->ad_drive_bits,
374162c8caf3SAda ata_ctlp->ac_iohandle1, ata_ctlp->ac_ioaddr1,
374262c8caf3SAda ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2,
374362c8caf3SAda &id) != ATA_DEV_DISK)
374462c8caf3SAda continue;
374562c8caf3SAda (void) ata_flush_cache(ata_ctlp, ata_drvp);
374662c8caf3SAda if (!ata_command(ata_ctlp, ata_drvp, TRUE, TRUE,
374762c8caf3SAda 5 * 1000000, cmd, 0, 0, 0, 0, 0, 0)) {
374862c8caf3SAda cmn_err(CE_WARN, "!ata_controller - Can not "
374962c8caf3SAda "put drive %d in to power mode %u",
375062c8caf3SAda targ, cmd);
375162c8caf3SAda (void) ata_devo_reset(dip, DDI_RESET_FORCE);
375262c8caf3SAda return (DDI_FAILURE);
375362c8caf3SAda }
37542df1fe9cSrandyf }
37552df1fe9cSrandyf return (DDI_SUCCESS);
375662c8caf3SAda }
37572df1fe9cSrandyf
375862c8caf3SAda (void) ata_software_reset(ata_ctlp);
37592df1fe9cSrandyf for (targ = 0; targ < ATA_MAXTARG; targ++) {
37602df1fe9cSrandyf ata_drvp = CTL2DRV(ata_ctlp, targ, 0);
376162c8caf3SAda if (ata_drvp == NULL)
37622df1fe9cSrandyf continue;
37632df1fe9cSrandyf ata_resume_drive(ata_drvp);
37642df1fe9cSrandyf
37652df1fe9cSrandyf if (ATAPIDRV(ata_drvp))
37662df1fe9cSrandyf lastlun = ata_drvp->ad_id.ai_lastlun;
37672df1fe9cSrandyf else
37682df1fe9cSrandyf lastlun = 0;
37692df1fe9cSrandyf if (!ata_enable_atapi_luns)
37702df1fe9cSrandyf lastlun = 0;
37712df1fe9cSrandyf for (lun = 1; lun <= lastlun && lun < ATA_MAXLUN; lun++) {
37722df1fe9cSrandyf ata_drvp = CTL2DRV(ata_ctlp, targ, lun);
37732df1fe9cSrandyf if (ata_drvp != NULL)
37742df1fe9cSrandyf ata_resume_drive(ata_drvp);
37752df1fe9cSrandyf }
37762df1fe9cSrandyf }
37772df1fe9cSrandyf
37782df1fe9cSrandyf return (DDI_SUCCESS);
37792df1fe9cSrandyf }
37802df1fe9cSrandyf
37812df1fe9cSrandyf /*
37822df1fe9cSrandyf * return 1 when ata controller is a pci device,
37832df1fe9cSrandyf * otherwise return 0
37842df1fe9cSrandyf */
37852df1fe9cSrandyf static int
ata_is_pci(dev_info_t * dip)37862df1fe9cSrandyf ata_is_pci(dev_info_t *dip)
37872df1fe9cSrandyf {
37882df1fe9cSrandyf int rc;
37892df1fe9cSrandyf char *bufp;
37902df1fe9cSrandyf int ispci;
37912df1fe9cSrandyf
37922df1fe9cSrandyf rc = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(dip),
37932df1fe9cSrandyf DDI_PROP_DONTPASS, "device_type", &bufp);
37942df1fe9cSrandyf
37952df1fe9cSrandyf if (rc != DDI_PROP_SUCCESS) {
37962df1fe9cSrandyf ADBG_ERROR(("ata_is_pci !device_type\n"));
37972df1fe9cSrandyf return (0);
37982df1fe9cSrandyf }
37992df1fe9cSrandyf
38002df1fe9cSrandyf ispci = (strcmp(bufp, "pci-ide") == 0);
38012df1fe9cSrandyf
38022df1fe9cSrandyf ddi_prop_free(bufp);
38032df1fe9cSrandyf
38042df1fe9cSrandyf return (ispci);
38052df1fe9cSrandyf }
38065fb86baeSml
38075fb86baeSml /*
38085fb86baeSml * Disable DMA for this drive
38095fb86baeSml */
38105fb86baeSml static void
ata_disable_DMA(ata_drv_t * ata_drvp)38115fb86baeSml ata_disable_DMA(ata_drv_t *ata_drvp)
38125fb86baeSml {
38135fb86baeSml struct ata_id *aidp;
38145fb86baeSml char buf[sizeof (aidp->ai_model) +2];
38155fb86baeSml int i;
38165fb86baeSml
38175fb86baeSml if (ata_drvp == NULL)
38185fb86baeSml return;
38195fb86baeSml
38205fb86baeSml if (ata_drvp->ad_pciide_dma == ATA_DMA_OFF)
38215fb86baeSml return;
38225fb86baeSml
38235fb86baeSml ata_drvp->ad_pciide_dma = ATA_DMA_OFF;
38245fb86baeSml
38255fb86baeSml /* Print the message */
38265fb86baeSml buf[0] = '\0';
38275fb86baeSml aidp = &ata_drvp->ad_id;
38285fb86baeSml if (aidp != NULL) {
38295fb86baeSml (void) strncpy(buf, aidp->ai_model, sizeof (aidp->ai_model));
38305fb86baeSml buf[sizeof (aidp->ai_model) -1] = '\0';
38315fb86baeSml for (i = sizeof (aidp->ai_model) - 2; buf[i] == ' '; i--)
38325fb86baeSml buf[i] = '\0';
38335fb86baeSml }
38345fb86baeSml cmn_err(CE_CONT,
38355fb86baeSml "?DMA disabled on %s target=%d, lun=%d due to DMA errors,",
38365fb86baeSml buf, ata_drvp->ad_targ, ata_drvp->ad_lun);
38375fb86baeSml cmn_err(CE_CONT, "?most likely due to the CF-to-IDE adapter.");
38385fb86baeSml }
3839c8531848Syt
3840c8531848Syt /*
3841c8531848Syt * Check and select DMA mode
3842c8531848Syt *
3843c8531848Syt * TRUE is returned when set feature is called successfully,
3844c8531848Syt * otherwise return FALSE
3845c8531848Syt */
3846c8531848Syt int
ata_set_dma_mode(ata_ctl_t * ata_ctlp,ata_drv_t * ata_drvp)3847c8531848Syt ata_set_dma_mode(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp)
3848c8531848Syt {
3849c8531848Syt struct ata_id *aidp;
3850c8531848Syt int mode, rval = FALSE;
3851c8531848Syt uint8_t subcmd;
3852c8531848Syt
3853c8531848Syt aidp = &ata_drvp->ad_id;
3854c8531848Syt
3855c8531848Syt /* Return directly if DMA is not supported */
3856c8531848Syt if (!(aidp->ai_cap & ATAC_DMA_SUPPORT))
3857c8531848Syt return (rval);
3858c8531848Syt
38598c97a06bSAda /* Return if DMA mode is already selected */
38608c97a06bSAda if (((aidp->ai_validinfo & ATAC_VALIDINFO_83) &&
38618c97a06bSAda (aidp->ai_ultradma & ATAC_UDMA_SEL_MASK)) ||
38628c97a06bSAda (aidp->ai_dworddma & ATAC_MDMA_SEL_MASK))
38638c97a06bSAda return (rval);
38648c97a06bSAda
3865c8531848Syt /* First check Ultra DMA mode if no DMA is selected */
3866c8531848Syt if ((aidp->ai_validinfo & ATAC_VALIDINFO_83) &&
3867c8531848Syt (aidp->ai_ultradma & ATAC_UDMA_SUP_MASK)) {
3868c8531848Syt for (mode = 6; mode >= 0; --mode) {
3869c8531848Syt if (aidp->ai_ultradma & (1 << mode))
3870c8531848Syt break;
3871c8531848Syt }
3872c8531848Syt subcmd = ATF_XFRMOD_UDMA;
3873c8531848Syt
3874c8531848Syt } else if (aidp->ai_dworddma & ATAC_MDMA_SUP_MASK) {
3875c8531848Syt /* Then check multi-word DMA mode */
3876c8531848Syt for (mode = 2; mode >= 0; --mode) {
3877c8531848Syt if (aidp->ai_dworddma & (1 << mode))
3878c8531848Syt break;
3879c8531848Syt }
3880c8531848Syt subcmd = ATF_XFRMOD_MDMA;
3881c8531848Syt
3882c8531848Syt } else {
3883c8531848Syt return (rval);
3884c8531848Syt }
3885c8531848Syt
3886c8531848Syt rval = ata_set_feature(ata_ctlp, ata_drvp, ATSF_SET_XFRMOD,
3887c8531848Syt subcmd|mode);
3888c8531848Syt
3889c8531848Syt return (rval);
3890c8531848Syt }
38910f1b305eSSeth Goldberg
38920f1b305eSSeth Goldberg /*
38930f1b305eSSeth Goldberg * Reset Ultra DMA mode / MWDMA mode
38940f1b305eSSeth Goldberg */
38950f1b305eSSeth Goldberg void
ata_reset_dma_mode(ata_drv_t * ata_drvp)38960f1b305eSSeth Goldberg ata_reset_dma_mode(ata_drv_t *ata_drvp)
38970f1b305eSSeth Goldberg {
38980f1b305eSSeth Goldberg uint8_t subcmd;
38990f1b305eSSeth Goldberg int mode;
39000f1b305eSSeth Goldberg ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
39010f1b305eSSeth Goldberg
39020f1b305eSSeth Goldberg switch (ata_drvp->ad_dma_cap) {
39030f1b305eSSeth Goldberg case ATA_DMA_ULTRAMODE:
39040f1b305eSSeth Goldberg subcmd = ATF_XFRMOD_UDMA;
39050f1b305eSSeth Goldberg for (mode = 0; mode <= 6; mode++) {
39060f1b305eSSeth Goldberg if (ata_drvp->ad_dma_mode & (1 << (mode + 8)))
39070f1b305eSSeth Goldberg break;
39080f1b305eSSeth Goldberg }
39090f1b305eSSeth Goldberg break;
39100f1b305eSSeth Goldberg case ATA_DMA_MWORDMODE:
39110f1b305eSSeth Goldberg subcmd = ATF_XFRMOD_MDMA;
39120f1b305eSSeth Goldberg mode = ((ata_drvp->ad_dma_mode & ATAC_MDMA_2_SEL) ==
39130f1b305eSSeth Goldberg ATAC_MDMA_2_SEL ? 2 :
39140f1b305eSSeth Goldberg (ata_drvp->ad_dma_mode & ATAC_MDMA_1_SEL) ==
39150f1b305eSSeth Goldberg ATAC_MDMA_1_SEL ? 1 : 0);
39160f1b305eSSeth Goldberg break;
39170f1b305eSSeth Goldberg default:
39180f1b305eSSeth Goldberg return;
39190f1b305eSSeth Goldberg }
39200f1b305eSSeth Goldberg
39210f1b305eSSeth Goldberg (void) ata_set_feature(ata_ctlp, ata_drvp, ATSF_SET_XFRMOD,
39220f1b305eSSeth Goldberg (subcmd | mode));
39230f1b305eSSeth Goldberg }
3924fe072f42SAda
3925fe072f42SAda /*
3926fe072f42SAda * Check DMA mode is the same with saved info
3927fe072f42SAda * return value: 0 - not same
3928fe072f42SAda * 1 - same
3929fe072f42SAda */
3930fe072f42SAda static int
ata_check_dma_mode(ata_drv_t * ata_drvp)3931fe072f42SAda ata_check_dma_mode(ata_drv_t *ata_drvp)
3932fe072f42SAda {
3933fe072f42SAda struct ata_id *aidp;
3934fe072f42SAda
3935fe072f42SAda aidp = &ata_drvp->ad_id;
3936fe072f42SAda switch (ata_drvp->ad_dma_cap) {
3937fe072f42SAda case ATA_DMA_ULTRAMODE:
3938fe072f42SAda if ((aidp->ai_validinfo & ATAC_VALIDINFO_83) &&
3939fe072f42SAda (aidp->ai_ultradma & ATAC_UDMA_SEL_MASK) &&
3940fe072f42SAda (aidp->ai_ultradma == ata_drvp->ad_dma_mode))
3941fe072f42SAda break;
3942fe072f42SAda else
3943fe072f42SAda return (0);
3944fe072f42SAda case ATA_DMA_MWORDMODE:
3945fe072f42SAda if ((aidp->ai_dworddma & ATAC_MDMA_SEL_MASK) &&
3946fe072f42SAda (aidp->ai_dworddma == ata_drvp->ad_dma_mode))
3947fe072f42SAda break;
3948fe072f42SAda else
3949fe072f42SAda return (0);
3950fe072f42SAda default:
3951fe072f42SAda return (0);
3952fe072f42SAda }
3953fe072f42SAda return (1);
3954fe072f42SAda }
3955