1 | /* $NetBSD: pciide_opti_reg.h,v 1.12 2008/04/28 20:23:55 martin Exp $ */ |
2 | |
3 | /*- |
4 | * Copyright (c) 2000 The NetBSD Foundation, Inc. |
5 | * All rights reserved. |
6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Steve C. Woodford. |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ |
31 | |
32 | /* |
33 | * Register definitions for OPTi PCIIDE controllers based on |
34 | * their 82c621 chip. |
35 | */ |
36 | |
37 | /* IDE Initialization Control Register */ |
38 | #define OPTI_REG_INIT_CONTROL 0x40 |
39 | #define OPTI_INIT_CONTROL_MODE_PIO_0 0 |
40 | #define OPTI_INIT_CONTROL_MODE_PIO_1 2 |
41 | #define OPTI_INIT_CONTROL_MODE_PIO_2 1 |
42 | #define OPTI_INIT_CONTROL_MODE_PIO_3 3 |
43 | #define OPTI_INIT_CONTROL_ADDR_RELOC (1u << 2) |
44 | #define OPTI_INIT_CONTROL_CH2_ENABLE 0 |
45 | #define OPTI_INIT_CONTROL_CH2_DISABLE (1u << 3) |
46 | #define OPTI_INIT_CONTROL_FIFO_16 0 |
47 | #define OPTI_INIT_CONTROL_FIFO_32 (1u << 5) |
48 | #define OPTI_INIT_CONTROL_FIFO_REQ_32 0 |
49 | #define OPTI_INIT_CONTROL_FIFO_REQ_30 (1u << 6) |
50 | #define OPTI_INIT_CONTROL_FIFO_REQ_28 (2u << 6) |
51 | #define OPTI_INIT_CONTROL_FIFO_REQ_26 (3u << 6) |
52 | |
53 | /* IDE Enhanced Features Register */ |
54 | #define OPTI_REG_ENH_FEAT 0x42 |
55 | #define OPTI_ENH_FEAT_X111_ENABLE (1u << 1) |
56 | #define OPTI_ENH_FEAT_CONCURRENT_MAST (1u << 2) |
57 | #define OPTI_ENH_FEAT_PCI_INVALIDATE (1u << 3) |
58 | #define OPTI_ENH_FEAT_IDE_CONCUR (1u << 4) |
59 | #define OPTI_ENH_FEAT_SLAVE_FIFO_ISA (1u << 5) |
60 | |
61 | /* IDE Enhanced Mode Register */ |
62 | #define OPTI_REG_ENH_MODE 0x43 |
63 | #define OPTI_ENH_MODE_MASK(c,d) (3u << (((c) * 4) + ((d) * 2))) |
64 | #define OPTI_ENH_MODE_USE_TIMING(c,d) 0 |
65 | #define OPTI_ENH_MODE(c,d,m) ((m) << (((c) * 4) + ((d) * 2))) |
66 | |
67 | /* Timing registers */ |
68 | #define OPTI_REG_READ_CYCLE_TIMING 0x00 |
69 | #define OPTI_REG_WRITE_CYCLE_TIMING 0x01 |
70 | #define OPTI_RECOVERY_TIME_SHIFT 0 |
71 | #define OPTI_PULSE_WIDTH_SHIFT 4 |
72 | |
73 | /* |
74 | * Control register. |
75 | */ |
76 | #define OPTI_REG_CONTROL 0x03 |
77 | #define OPTI_CONTROL_DISABLE 0x11 |
78 | #define OPTI_CONTROL_ENABLE 0x95 |
79 | |
80 | /* Strap register */ |
81 | #define OPTI_REG_STRAP 0x05 |
82 | #define OPTI_STRAP_PCI_SPEED_MASK 0x1u |
83 | #define OPTI_STRAP_PCI_33 0 |
84 | #define OPTI_STRAP_PCI_25 1 |
85 | |
86 | /* Miscellaneous register */ |
87 | #define OPTI_REG_MISC 0x06 |
88 | #define OPTI_MISC_INDEX(d) ((unsigned)(d)) |
89 | #define OPTI_MISC_INDEX_MASK 0x01u |
90 | #define OPTI_MISC_DELAY_MASK 0x07u |
91 | #define OPTI_MISC_DELAY_SHIFT 1 |
92 | #define OPTI_MISC_ADDR_SETUP_MASK 0x3u |
93 | #define OPTI_MISC_ADDR_SETUP_SHIFT 4 |
94 | #define OPTI_MISC_READ_PREFETCH_ENABLE (1u << 6) |
95 | #define OPTI_MISC_ADDR_SETUP_MASK 0x3u |
96 | #define OPTI_MISC_WRITE_MASK 0x7fu |
97 | |
98 | |
99 | /* |
100 | * Inline functions for accessing the timing registers of the |
101 | * OPTi controller. |
102 | * |
103 | * These *MUST* disable interrupts as they need atomic access to |
104 | * certain magic registers. Failure to adhere to this *will* |
105 | * break things in subtle ways if the wdc registers are accessed |
106 | * by an interrupt routine while this magic sequence is executing. |
107 | */ |
108 | static __inline u_int8_t __unused |
109 | opti_read_config(struct ata_channel *chp, int reg) |
110 | { |
111 | struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp); |
112 | u_int8_t rv; |
113 | int s = splhigh(); |
114 | |
115 | /* Two consecutive 16-bit reads from register #1 (0x1f1/0x171) */ |
116 | (void) bus_space_read_2(wdr->cmd_iot, wdr->cmd_iohs[wd_features], 0); |
117 | (void) bus_space_read_2(wdr->cmd_iot, wdr->cmd_iohs[wd_features], 0); |
118 | |
119 | /* Followed by an 8-bit write of 0x3 to register #2 */ |
120 | bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt], 0, 0x03u); |
121 | |
122 | /* Now we can read the required register */ |
123 | rv = bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[reg], 0); |
124 | |
125 | /* Restore the real registers */ |
126 | bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt], 0, 0x83u); |
127 | |
128 | splx(s); |
129 | |
130 | return rv; |
131 | } |
132 | |
133 | static __inline void __unused |
134 | opti_write_config(struct ata_channel *chp, int reg, u_int8_t val) |
135 | { |
136 | struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp); |
137 | int s = splhigh(); |
138 | |
139 | /* Two consecutive 16-bit reads from register #1 (0x1f1/0x171) */ |
140 | (void) bus_space_read_2(wdr->cmd_iot, wdr->cmd_iohs[wd_features], 0); |
141 | (void) bus_space_read_2(wdr->cmd_iot, wdr->cmd_iohs[wd_features], 0); |
142 | |
143 | /* Followed by an 8-bit write of 0x3 to register #2 */ |
144 | bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt], 0, 0x03u); |
145 | |
146 | /* Now we can write the required register */ |
147 | bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[reg], 0, val); |
148 | |
149 | /* Restore the real registers */ |
150 | bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt], 0, 0x83u); |
151 | |
152 | splx(s); |
153 | } |
154 | |
155 | /* |
156 | * These are the timing register values for the various IDE modes |
157 | * supported by the OPTi chip. The first index of the two-dimensional |
158 | * arrays is used for a 33MHz PCIbus, the second for a 25MHz PCIbus. |
159 | */ |
160 | static const u_int8_t opti_tim_cp[2][8] __unused = { |
161 | /* Command Pulse */ |
162 | {5, 4, 3, 2, 2, 7, 2, 2}, |
163 | {4, 3, 2, 2, 1, 5, 2, 1} |
164 | }; |
165 | |
166 | static const u_int8_t opti_tim_rt[2][8] __unused = { |
167 | /* Recovery Time */ |
168 | {9, 4, 0, 0, 0, 6, 0, 0}, |
169 | {6, 2, 0, 0, 0, 4, 0, 0} |
170 | }; |
171 | |
172 | static const u_int8_t opti_tim_as[2][8] __unused = { |
173 | /* Address Setup */ |
174 | {2, 1, 1, 1, 0, 0, 0, 0}, |
175 | {1, 1, 0, 0, 0, 0, 0, 0} |
176 | }; |
177 | |
178 | static const u_int8_t opti_tim_em[8] __unused = { |
179 | /* Enhanced Mode */ |
180 | 0, 0, 0, 1, 2, 0, 1 ,2 |
181 | }; |
182 | |