Tue Jan 17 16:32:04 2012 UTC ()
Add and enable detachment and child detachment functions.


(jakllsch)
diff -r1.4 -r1.5 src/sys/dev/isa/wbsio.c

cvs diff -r1.4 -r1.5 src/sys/dev/isa/wbsio.c (switch to unified diff)

--- src/sys/dev/isa/wbsio.c 2012/01/17 16:28:33 1.4
+++ src/sys/dev/isa/wbsio.c 2012/01/17 16:32:03 1.5
@@ -1,243 +1,263 @@ @@ -1,243 +1,263 @@
1/* $NetBSD: wbsio.c,v 1.4 2012/01/17 16:28:33 jakllsch Exp $ */ 1/* $NetBSD: wbsio.c,v 1.5 2012/01/17 16:32:03 jakllsch Exp $ */
2/* $OpenBSD: wbsio.c,v 1.5 2009/03/29 21:53:52 sthen Exp $ */ 2/* $OpenBSD: wbsio.c,v 1.5 2009/03/29 21:53:52 sthen Exp $ */
3/* 3/*
4 * Copyright (c) 2008 Mark Kettenis <kettenis@openbsd.org> 4 * Copyright (c) 2008 Mark Kettenis <kettenis@openbsd.org>
5 * 5 *
6 * Permission to use, copy, modify, and distribute this software for any 6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies. 8 * copyright notice and this permission notice appear in all copies.
9 * 9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */ 17 */
18 18
19/* 19/*
20 * Winbond LPC Super I/O driver. 20 * Winbond LPC Super I/O driver.
21 */ 21 */
22 22
23#include <sys/param.h> 23#include <sys/param.h>
24#include <sys/device.h> 24#include <sys/device.h>
25#include <sys/kernel.h> 25#include <sys/kernel.h>
26#include <sys/systm.h> 26#include <sys/systm.h>
27 27
28#include <sys/bus.h> 28#include <sys/bus.h>
29 29
30#include <dev/isa/isareg.h> 30#include <dev/isa/isareg.h>
31#include <dev/isa/isavar.h> 31#include <dev/isa/isavar.h>
32 32
33/* ISA bus registers */ 33/* ISA bus registers */
34#define WBSIO_INDEX 0x00 /* Configuration Index Register */ 34#define WBSIO_INDEX 0x00 /* Configuration Index Register */
35#define WBSIO_DATA 0x01 /* Configuration Data Register */ 35#define WBSIO_DATA 0x01 /* Configuration Data Register */
36 36
37#define WBSIO_IOSIZE 0x02 /* ISA I/O space size */ 37#define WBSIO_IOSIZE 0x02 /* ISA I/O space size */
38 38
39#define WBSIO_CONF_EN_MAGIC 0x87 /* enable configuration mode */ 39#define WBSIO_CONF_EN_MAGIC 0x87 /* enable configuration mode */
40#define WBSIO_CONF_DS_MAGIC 0xaa /* disable configuration mode */ 40#define WBSIO_CONF_DS_MAGIC 0xaa /* disable configuration mode */
41 41
42/* Configuration Space Registers */ 42/* Configuration Space Registers */
43#define WBSIO_LDN 0x07 /* Logical Device Number */ 43#define WBSIO_LDN 0x07 /* Logical Device Number */
44#define WBSIO_ID 0x20 /* Device ID */ 44#define WBSIO_ID 0x20 /* Device ID */
45#define WBSIO_REV 0x21 /* Device Revision */ 45#define WBSIO_REV 0x21 /* Device Revision */
46 46
47#define WBSIO_ID_W83627HF 0x52 47#define WBSIO_ID_W83627HF 0x52
48#define WBSIO_ID_W83627THF 0x82 48#define WBSIO_ID_W83627THF 0x82
49#define WBSIO_ID_W83627EHF 0x88 49#define WBSIO_ID_W83627EHF 0x88
50#define WBSIO_ID_W83627DHG 0xa0 50#define WBSIO_ID_W83627DHG 0xa0
51#define WBSIO_ID_W83627SF 0x59 51#define WBSIO_ID_W83627SF 0x59
52#define WBSIO_ID_W83637HF 0x70 52#define WBSIO_ID_W83637HF 0x70
53#define WBSIO_ID_W83667HG 0xa5 53#define WBSIO_ID_W83667HG 0xa5
54#define WBSIO_ID_W83697HF 0x60 54#define WBSIO_ID_W83697HF 0x60
55 55
56/* Logical Device Number (LDN) Assignments */ 56/* Logical Device Number (LDN) Assignments */
57#define WBSIO_LDN_HM 0x0b 57#define WBSIO_LDN_HM 0x0b
58 58
59/* Hardware Monitor Control Registers (LDN B) */ 59/* Hardware Monitor Control Registers (LDN B) */
60#define WBSIO_HM_ADDR_MSB 0x60 /* Address [15:8] */ 60#define WBSIO_HM_ADDR_MSB 0x60 /* Address [15:8] */
61#define WBSIO_HM_ADDR_LSB 0x61 /* Address [7:0] */ 61#define WBSIO_HM_ADDR_LSB 0x61 /* Address [7:0] */
62 62
63struct wbsio_softc { 63struct wbsio_softc {
64 struct device sc_dev; 64 struct device sc_dev;
65 65
66 bus_space_tag_t sc_iot; 66 bus_space_tag_t sc_iot;
67 bus_space_handle_t sc_ioh; 67 bus_space_handle_t sc_ioh;
68}; 68};
69 69
70int wbsio_probe(device_t, cfdata_t, void *); 70int wbsio_probe(device_t, cfdata_t, void *);
71void wbsio_attach(device_t, device_t, void *); 71void wbsio_attach(device_t, device_t, void *);
 72int wbsio_detach(device_t, int);
 73void wbsio_childdet(device_t, device_t);
72int wbsio_print(void *, const char *); 74int wbsio_print(void *, const char *);
73 75
74CFATTACH_DECL_NEW(wbsio, sizeof(struct wbsio_softc), 76CFATTACH_DECL2_NEW(wbsio, sizeof(struct wbsio_softc),
75 wbsio_probe, wbsio_attach, NULL, NULL); 77 wbsio_probe, wbsio_attach, wbsio_detach, NULL, NULL, wbsio_childdet);
76 78
77static __inline void 79static __inline void
78wbsio_conf_enable(bus_space_tag_t iot, bus_space_handle_t ioh) 80wbsio_conf_enable(bus_space_tag_t iot, bus_space_handle_t ioh)
79{ 81{
80 bus_space_write_1(iot, ioh, WBSIO_INDEX, WBSIO_CONF_EN_MAGIC); 82 bus_space_write_1(iot, ioh, WBSIO_INDEX, WBSIO_CONF_EN_MAGIC);
81 bus_space_write_1(iot, ioh, WBSIO_INDEX, WBSIO_CONF_EN_MAGIC); 83 bus_space_write_1(iot, ioh, WBSIO_INDEX, WBSIO_CONF_EN_MAGIC);
82} 84}
83 85
84static __inline void 86static __inline void
85wbsio_conf_disable(bus_space_tag_t iot, bus_space_handle_t ioh) 87wbsio_conf_disable(bus_space_tag_t iot, bus_space_handle_t ioh)
86{ 88{
87 bus_space_write_1(iot, ioh, WBSIO_INDEX, WBSIO_CONF_DS_MAGIC); 89 bus_space_write_1(iot, ioh, WBSIO_INDEX, WBSIO_CONF_DS_MAGIC);
88} 90}
89 91
90static __inline u_int8_t 92static __inline u_int8_t
91wbsio_conf_read(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t index) 93wbsio_conf_read(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t index)
92{ 94{
93 bus_space_write_1(iot, ioh, WBSIO_INDEX, index); 95 bus_space_write_1(iot, ioh, WBSIO_INDEX, index);
94 return (bus_space_read_1(iot, ioh, WBSIO_DATA)); 96 return (bus_space_read_1(iot, ioh, WBSIO_DATA));
95} 97}
96 98
97static __inline void 99static __inline void
98wbsio_conf_write(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t index, 100wbsio_conf_write(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t index,
99 u_int8_t data) 101 u_int8_t data)
100{ 102{
101 bus_space_write_1(iot, ioh, WBSIO_INDEX, index); 103 bus_space_write_1(iot, ioh, WBSIO_INDEX, index);
102 bus_space_write_1(iot, ioh, WBSIO_DATA, data); 104 bus_space_write_1(iot, ioh, WBSIO_DATA, data);
103} 105}
104 106
105int 107int
106wbsio_probe(device_t parent, cfdata_t match, void *aux) 108wbsio_probe(device_t parent, cfdata_t match, void *aux)
107{ 109{
108 struct isa_attach_args *ia = aux; 110 struct isa_attach_args *ia = aux;
109 bus_space_tag_t iot; 111 bus_space_tag_t iot;
110 bus_space_handle_t ioh; 112 bus_space_handle_t ioh;
111 u_int8_t reg; 113 u_int8_t reg;
112 114
113 /* Must supply an address */ 115 /* Must supply an address */
114 if (ia->ia_nio < 1) 116 if (ia->ia_nio < 1)
115 return 0; 117 return 0;
116 118
117 if (ISA_DIRECT_CONFIG(ia)) 119 if (ISA_DIRECT_CONFIG(ia))
118 return 0; 120 return 0;
119 121
120 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 122 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
121 return 0; 123 return 0;
122 124
123 /* Match by device ID */ 125 /* Match by device ID */
124 iot = ia->ia_iot; 126 iot = ia->ia_iot;
125 if (bus_space_map(iot, ia->ia_io[0].ir_addr, WBSIO_IOSIZE, 0, &ioh)) 127 if (bus_space_map(iot, ia->ia_io[0].ir_addr, WBSIO_IOSIZE, 0, &ioh))
126 return 0; 128 return 0;
127 wbsio_conf_enable(iot, ioh); 129 wbsio_conf_enable(iot, ioh);
128 reg = wbsio_conf_read(iot, ioh, WBSIO_ID); 130 reg = wbsio_conf_read(iot, ioh, WBSIO_ID);
129 aprint_debug("wbsio_probe: id 0x%02x\n", reg); 131 aprint_debug("wbsio_probe: id 0x%02x\n", reg);
130 wbsio_conf_disable(iot, ioh); 132 wbsio_conf_disable(iot, ioh);
131 bus_space_unmap(iot, ioh, WBSIO_IOSIZE); 133 bus_space_unmap(iot, ioh, WBSIO_IOSIZE);
132 switch (reg) { 134 switch (reg) {
133 case WBSIO_ID_W83627HF: 135 case WBSIO_ID_W83627HF:
134 case WBSIO_ID_W83627THF: 136 case WBSIO_ID_W83627THF:
135 case WBSIO_ID_W83627EHF: 137 case WBSIO_ID_W83627EHF:
136 case WBSIO_ID_W83627DHG: 138 case WBSIO_ID_W83627DHG:
137 case WBSIO_ID_W83637HF: 139 case WBSIO_ID_W83637HF:
138 case WBSIO_ID_W83697HF: 140 case WBSIO_ID_W83697HF:
139 ia->ia_nio = 1; 141 ia->ia_nio = 1;
140 ia->ia_io[0].ir_size = WBSIO_IOSIZE; 142 ia->ia_io[0].ir_size = WBSIO_IOSIZE;
141 ia->ia_niomem = 0; 143 ia->ia_niomem = 0;
142 ia->ia_nirq = 0; 144 ia->ia_nirq = 0;
143 ia->ia_ndrq = 0; 145 ia->ia_ndrq = 0;
144 return 1; 146 return 1;
145 } 147 }
146 148
147 return 0; 149 return 0;
148} 150}
149 151
150void 152void
151wbsio_attach(device_t parent, device_t self, void *aux) 153wbsio_attach(device_t parent, device_t self, void *aux)
152{ 154{
153 struct wbsio_softc *sc = (void *)self; 155 struct wbsio_softc *sc = (void *)self;
154 struct isa_attach_args *ia = aux; 156 struct isa_attach_args *ia = aux;
155 struct isa_attach_args nia; 157 struct isa_attach_args nia;
156 const char *desc = NULL; 158 const char *desc = NULL;
157 u_int8_t reg, reg0, reg1; 159 u_int8_t reg, reg0, reg1;
158 u_int16_t iobase; 160 u_int16_t iobase;
159 161
160 /* Map ISA I/O space */ 162 /* Map ISA I/O space */
161 sc->sc_iot = ia->ia_iot; 163 sc->sc_iot = ia->ia_iot;
162 if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, 164 if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr,
163 WBSIO_IOSIZE, 0, &sc->sc_ioh)) { 165 WBSIO_IOSIZE, 0, &sc->sc_ioh)) {
164 aprint_error(": can't map i/o space\n"); 166 aprint_error(": can't map i/o space\n");
165 return; 167 return;
166 } 168 }
167 169
168 /* Enter configuration mode */ 170 /* Enter configuration mode */
169 wbsio_conf_enable(sc->sc_iot, sc->sc_ioh); 171 wbsio_conf_enable(sc->sc_iot, sc->sc_ioh);
170 172
171 /* Read device ID */ 173 /* Read device ID */
172 reg = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_ID); 174 reg = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_ID);
173 switch (reg) { 175 switch (reg) {
174 case WBSIO_ID_W83627HF: 176 case WBSIO_ID_W83627HF:
175 desc = "W83627HF"; 177 desc = "W83627HF";
176 break; 178 break;
177 case WBSIO_ID_W83627THF: 179 case WBSIO_ID_W83627THF:
178 desc = "W83627THF"; 180 desc = "W83627THF";
179 break; 181 break;
180 case WBSIO_ID_W83627EHF: 182 case WBSIO_ID_W83627EHF:
181 desc = "W83627EHF"; 183 desc = "W83627EHF";
182 break; 184 break;
183 case WBSIO_ID_W83627DHG: 185 case WBSIO_ID_W83627DHG:
184 desc = "W83627DHG"; 186 desc = "W83627DHG";
185 break; 187 break;
186 case WBSIO_ID_W83637HF: 188 case WBSIO_ID_W83637HF:
187 desc = "W83637HF"; 189 desc = "W83637HF";
188 break; 190 break;
189 case WBSIO_ID_W83667HG: 191 case WBSIO_ID_W83667HG:
190 desc = "W83667HG"; 192 desc = "W83667HG";
191 break; 193 break;
192 case WBSIO_ID_W83697HF: 194 case WBSIO_ID_W83697HF:
193 desc = "W83697HF"; 195 desc = "W83697HF";
194 break; 196 break;
195 } 197 }
196 198
197 /* Read device revision */ 199 /* Read device revision */
198 reg = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_REV); 200 reg = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_REV);
199 201
200 aprint_naive("\n"); 202 aprint_naive("\n");
201 aprint_normal(": Winbond LPC Super I/O %s rev 0x%02x\n", desc, reg); 203 aprint_normal(": Winbond LPC Super I/O %s rev 0x%02x\n", desc, reg);
202 204
203 /* Select HM logical device */ 205 /* Select HM logical device */
204 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_HM); 206 wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_HM);
205 207
206 /* 208 /*
207 * The address should be 8-byte aligned, but it seems some 209 * The address should be 8-byte aligned, but it seems some
208 * BIOSes ignore this. They get away with it, because 210 * BIOSes ignore this. They get away with it, because
209 * Apparently the hardware simply ignores the lower three 211 * Apparently the hardware simply ignores the lower three
210 * bits. We do the same here. 212 * bits. We do the same here.
211 */ 213 */
212 reg0 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_HM_ADDR_LSB); 214 reg0 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_HM_ADDR_LSB);
213 reg1 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_HM_ADDR_MSB); 215 reg1 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_HM_ADDR_MSB);
214 iobase = (reg1 << 8) | (reg0 & ~0x7); 216 iobase = (reg1 << 8) | (reg0 & ~0x7);
215 217
216 /* Escape from configuration mode */ 218 /* Escape from configuration mode */
217 wbsio_conf_disable(sc->sc_iot, sc->sc_ioh); 219 wbsio_conf_disable(sc->sc_iot, sc->sc_ioh);
218 220
219 if (!pmf_device_register(self, NULL, NULL)) 221 if (!pmf_device_register(self, NULL, NULL))
220 aprint_error_dev(self, "couldn't establish power handler\n"); 222 aprint_error_dev(self, "couldn't establish power handler\n");
221 223
222 if (iobase == 0) 224 if (iobase == 0)
223 return; 225 return;
224 226
225 nia = *ia; 227 nia = *ia;
226 nia.ia_io[0].ir_addr = iobase; 228 nia.ia_io[0].ir_addr = iobase;
227 config_found(self, &nia, wbsio_print); 229 config_found(self, &nia, wbsio_print);
228} 230}
229 231
230int 232int
 233wbsio_detach(device_t self, int flags)
 234{
 235 int rc;
 236
 237 if ((rc = config_detach_children(self, flags)) != 0)
 238 return rc;
 239 bus_space_unmap(sc->sc_iot, sc->sc_ioh, WBSIO_IOSIZE);
 240 pmf_device_deregister(self);
 241 return 0;
 242}
 243
 244void
 245wbsio_childdet(device_t self, device_t child)
 246{
 247 return;
 248}
 249
 250int
231wbsio_print(void *aux, const char *pnp) 251wbsio_print(void *aux, const char *pnp)
232{ 252{
233 struct isa_attach_args *ia = aux; 253 struct isa_attach_args *ia = aux;
234 254
235 if (pnp) 255 if (pnp)
236 aprint_normal("%s", pnp); 256 aprint_normal("%s", pnp);
237 if (ia->ia_io[0].ir_size) 257 if (ia->ia_io[0].ir_size)
238 aprint_normal(" port 0x%x", ia->ia_io[0].ir_addr); 258 aprint_normal(" port 0x%x", ia->ia_io[0].ir_addr);
239 if (ia->ia_io[0].ir_size > 1) 259 if (ia->ia_io[0].ir_size > 1)
240 aprint_normal("-0x%x", ia->ia_io[0].ir_addr + 260 aprint_normal("-0x%x", ia->ia_io[0].ir_addr +
241 ia->ia_io[0].ir_size - 1); 261 ia->ia_io[0].ir_size - 1);
242 return (UNCONF); 262 return (UNCONF);
243} 263}