diff options
Diffstat (limited to 'drivers/parport/parport_cs.c')
-rw-r--r-- | drivers/parport/parport_cs.c | 129 |
1 files changed, 36 insertions, 93 deletions
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index 158d92563259..b953d5907c05 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c | |||
@@ -81,15 +81,15 @@ static char *version = | |||
81 | #define FORCE_EPP_MODE 0x08 | 81 | #define FORCE_EPP_MODE 0x08 |
82 | 82 | ||
83 | typedef struct parport_info_t { | 83 | typedef struct parport_info_t { |
84 | dev_link_t link; | 84 | struct pcmcia_device *p_dev; |
85 | int ndev; | 85 | int ndev; |
86 | dev_node_t node; | 86 | dev_node_t node; |
87 | struct parport *port; | 87 | struct parport *port; |
88 | } parport_info_t; | 88 | } parport_info_t; |
89 | 89 | ||
90 | static void parport_detach(struct pcmcia_device *p_dev); | 90 | static void parport_detach(struct pcmcia_device *p_dev); |
91 | static void parport_config(dev_link_t *link); | 91 | static int parport_config(struct pcmcia_device *link); |
92 | static void parport_cs_release(dev_link_t *); | 92 | static void parport_cs_release(struct pcmcia_device *); |
93 | 93 | ||
94 | /*====================================================================== | 94 | /*====================================================================== |
95 | 95 | ||
@@ -99,10 +99,9 @@ static void parport_cs_release(dev_link_t *); | |||
99 | 99 | ||
100 | ======================================================================*/ | 100 | ======================================================================*/ |
101 | 101 | ||
102 | static int parport_attach(struct pcmcia_device *p_dev) | 102 | static int parport_probe(struct pcmcia_device *link) |
103 | { | 103 | { |
104 | parport_info_t *info; | 104 | parport_info_t *info; |
105 | dev_link_t *link; | ||
106 | 105 | ||
107 | DEBUG(0, "parport_attach()\n"); | 106 | DEBUG(0, "parport_attach()\n"); |
108 | 107 | ||
@@ -110,23 +109,17 @@ static int parport_attach(struct pcmcia_device *p_dev) | |||
110 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 109 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
111 | if (!info) return -ENOMEM; | 110 | if (!info) return -ENOMEM; |
112 | memset(info, 0, sizeof(*info)); | 111 | memset(info, 0, sizeof(*info)); |
113 | link = &info->link; link->priv = info; | 112 | link->priv = info; |
113 | info->p_dev = link; | ||
114 | 114 | ||
115 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 115 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
116 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; | 116 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; |
117 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 117 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
118 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 118 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
119 | link->conf.Attributes = CONF_ENABLE_IRQ; | 119 | link->conf.Attributes = CONF_ENABLE_IRQ; |
120 | link->conf.Vcc = 50; | ||
121 | link->conf.IntType = INT_MEMORY_AND_IO; | 120 | link->conf.IntType = INT_MEMORY_AND_IO; |
122 | 121 | ||
123 | link->handle = p_dev; | 122 | return parport_config(link); |
124 | p_dev->instance = link; | ||
125 | |||
126 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
127 | parport_config(link); | ||
128 | |||
129 | return 0; | ||
130 | } /* parport_attach */ | 123 | } /* parport_attach */ |
131 | 124 | ||
132 | /*====================================================================== | 125 | /*====================================================================== |
@@ -138,14 +131,11 @@ static int parport_attach(struct pcmcia_device *p_dev) | |||
138 | 131 | ||
139 | ======================================================================*/ | 132 | ======================================================================*/ |
140 | 133 | ||
141 | static void parport_detach(struct pcmcia_device *p_dev) | 134 | static void parport_detach(struct pcmcia_device *link) |
142 | { | 135 | { |
143 | dev_link_t *link = dev_to_instance(p_dev); | ||
144 | |||
145 | DEBUG(0, "parport_detach(0x%p)\n", link); | 136 | DEBUG(0, "parport_detach(0x%p)\n", link); |
146 | 137 | ||
147 | if (link->state & DEV_CONFIG) | 138 | parport_cs_release(link); |
148 | parport_cs_release(link); | ||
149 | 139 | ||
150 | kfree(link->priv); | 140 | kfree(link->priv); |
151 | } /* parport_detach */ | 141 | } /* parport_detach */ |
@@ -161,14 +151,12 @@ static void parport_detach(struct pcmcia_device *p_dev) | |||
161 | #define CS_CHECK(fn, ret) \ | 151 | #define CS_CHECK(fn, ret) \ |
162 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 152 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
163 | 153 | ||
164 | void parport_config(dev_link_t *link) | 154 | static int parport_config(struct pcmcia_device *link) |
165 | { | 155 | { |
166 | client_handle_t handle = link->handle; | ||
167 | parport_info_t *info = link->priv; | 156 | parport_info_t *info = link->priv; |
168 | tuple_t tuple; | 157 | tuple_t tuple; |
169 | u_short buf[128]; | 158 | u_short buf[128]; |
170 | cisparse_t parse; | 159 | cisparse_t parse; |
171 | config_info_t conf; | ||
172 | cistpl_cftable_entry_t *cfg = &parse.cftable_entry; | 160 | cistpl_cftable_entry_t *cfg = &parse.cftable_entry; |
173 | cistpl_cftable_entry_t dflt = { 0 }; | 161 | cistpl_cftable_entry_t dflt = { 0 }; |
174 | struct parport *p; | 162 | struct parport *p; |
@@ -180,24 +168,18 @@ void parport_config(dev_link_t *link) | |||
180 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; | 168 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; |
181 | tuple.Attributes = 0; | 169 | tuple.Attributes = 0; |
182 | tuple.DesiredTuple = CISTPL_CONFIG; | 170 | tuple.DesiredTuple = CISTPL_CONFIG; |
183 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 171 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
184 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 172 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
185 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 173 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
186 | link->conf.ConfigBase = parse.config.base; | 174 | link->conf.ConfigBase = parse.config.base; |
187 | link->conf.Present = parse.config.rmask[0]; | 175 | link->conf.Present = parse.config.rmask[0]; |
188 | |||
189 | /* Configure card */ | ||
190 | link->state |= DEV_CONFIG; | ||
191 | 176 | ||
192 | /* Not sure if this is right... look up the current Vcc */ | ||
193 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); | ||
194 | |||
195 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 177 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
196 | tuple.Attributes = 0; | 178 | tuple.Attributes = 0; |
197 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 179 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
198 | while (1) { | 180 | while (1) { |
199 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 || | 181 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || |
200 | pcmcia_parse_tuple(handle, &tuple, &parse) != 0) | 182 | pcmcia_parse_tuple(link, &tuple, &parse) != 0) |
201 | goto next_entry; | 183 | goto next_entry; |
202 | 184 | ||
203 | if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { | 185 | if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { |
@@ -212,7 +194,7 @@ void parport_config(dev_link_t *link) | |||
212 | link->io.BasePort2 = io->win[1].base; | 194 | link->io.BasePort2 = io->win[1].base; |
213 | link->io.NumPorts2 = io->win[1].len; | 195 | link->io.NumPorts2 = io->win[1].len; |
214 | } | 196 | } |
215 | if (pcmcia_request_io(link->handle, &link->io) != 0) | 197 | if (pcmcia_request_io(link, &link->io) != 0) |
216 | goto next_entry; | 198 | goto next_entry; |
217 | /* If we've got this far, we're done */ | 199 | /* If we've got this far, we're done */ |
218 | break; | 200 | break; |
@@ -220,15 +202,12 @@ void parport_config(dev_link_t *link) | |||
220 | 202 | ||
221 | next_entry: | 203 | next_entry: |
222 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; | 204 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; |
223 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); | 205 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); |
224 | } | 206 | } |
225 | 207 | ||
226 | CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); | 208 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
227 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); | 209 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
228 | 210 | ||
229 | release_region(link->io.BasePort1, link->io.NumPorts1); | ||
230 | if (link->io.NumPorts2) | ||
231 | release_region(link->io.BasePort2, link->io.NumPorts2); | ||
232 | p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2, | 211 | p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2, |
233 | link->irq.AssignedIRQ, PARPORT_DMA_NONE, | 212 | link->irq.AssignedIRQ, PARPORT_DMA_NONE, |
234 | NULL); | 213 | NULL); |
@@ -247,17 +226,15 @@ void parport_config(dev_link_t *link) | |||
247 | info->node.minor = p->number; | 226 | info->node.minor = p->number; |
248 | info->port = p; | 227 | info->port = p; |
249 | strcpy(info->node.dev_name, p->name); | 228 | strcpy(info->node.dev_name, p->name); |
250 | link->dev = &info->node; | 229 | link->dev_node = &info->node; |
230 | |||
231 | return 0; | ||
251 | 232 | ||
252 | link->state &= ~DEV_CONFIG_PENDING; | ||
253 | return; | ||
254 | |||
255 | cs_failed: | 233 | cs_failed: |
256 | cs_error(link->handle, last_fn, last_ret); | 234 | cs_error(link, last_fn, last_ret); |
257 | failed: | 235 | failed: |
258 | parport_cs_release(link); | 236 | parport_cs_release(link); |
259 | link->state &= ~DEV_CONFIG_PENDING; | 237 | return -ENODEV; |
260 | |||
261 | } /* parport_config */ | 238 | } /* parport_config */ |
262 | 239 | ||
263 | /*====================================================================== | 240 | /*====================================================================== |
@@ -268,53 +245,21 @@ failed: | |||
268 | 245 | ||
269 | ======================================================================*/ | 246 | ======================================================================*/ |
270 | 247 | ||
271 | void parport_cs_release(dev_link_t *link) | 248 | void parport_cs_release(struct pcmcia_device *link) |
272 | { | ||
273 | parport_info_t *info = link->priv; | ||
274 | |||
275 | DEBUG(0, "parport_release(0x%p)\n", link); | ||
276 | |||
277 | if (info->ndev) { | ||
278 | struct parport *p = info->port; | ||
279 | parport_pc_unregister_port(p); | ||
280 | request_region(link->io.BasePort1, link->io.NumPorts1, | ||
281 | info->node.dev_name); | ||
282 | if (link->io.NumPorts2) | ||
283 | request_region(link->io.BasePort2, link->io.NumPorts2, | ||
284 | info->node.dev_name); | ||
285 | } | ||
286 | info->ndev = 0; | ||
287 | link->dev = NULL; | ||
288 | |||
289 | pcmcia_release_configuration(link->handle); | ||
290 | pcmcia_release_io(link->handle, &link->io); | ||
291 | pcmcia_release_irq(link->handle, &link->irq); | ||
292 | |||
293 | link->state &= ~DEV_CONFIG; | ||
294 | |||
295 | } /* parport_cs_release */ | ||
296 | |||
297 | static int parport_suspend(struct pcmcia_device *dev) | ||
298 | { | 249 | { |
299 | dev_link_t *link = dev_to_instance(dev); | 250 | parport_info_t *info = link->priv; |
300 | 251 | ||
301 | link->state |= DEV_SUSPEND; | 252 | DEBUG(0, "parport_release(0x%p)\n", link); |
302 | if (link->state & DEV_CONFIG) | ||
303 | pcmcia_release_configuration(link->handle); | ||
304 | 253 | ||
305 | return 0; | 254 | if (info->ndev) { |
306 | } | 255 | struct parport *p = info->port; |
307 | 256 | parport_pc_unregister_port(p); | |
308 | static int parport_resume(struct pcmcia_device *dev) | 257 | } |
309 | { | 258 | info->ndev = 0; |
310 | dev_link_t *link = dev_to_instance(dev); | ||
311 | 259 | ||
312 | link->state &= ~DEV_SUSPEND; | 260 | pcmcia_disable_device(link); |
313 | if (DEV_OK(link)) | 261 | } /* parport_cs_release */ |
314 | pcmcia_request_configuration(link->handle, &link->conf); | ||
315 | 262 | ||
316 | return 0; | ||
317 | } | ||
318 | 263 | ||
319 | static struct pcmcia_device_id parport_ids[] = { | 264 | static struct pcmcia_device_id parport_ids[] = { |
320 | PCMCIA_DEVICE_FUNC_ID(3), | 265 | PCMCIA_DEVICE_FUNC_ID(3), |
@@ -328,11 +273,9 @@ static struct pcmcia_driver parport_cs_driver = { | |||
328 | .drv = { | 273 | .drv = { |
329 | .name = "parport_cs", | 274 | .name = "parport_cs", |
330 | }, | 275 | }, |
331 | .probe = parport_attach, | 276 | .probe = parport_probe, |
332 | .remove = parport_detach, | 277 | .remove = parport_detach, |
333 | .id_table = parport_ids, | 278 | .id_table = parport_ids, |
334 | .suspend = parport_suspend, | ||
335 | .resume = parport_resume, | ||
336 | }; | 279 | }; |
337 | 280 | ||
338 | static int __init init_parport_cs(void) | 281 | static int __init init_parport_cs(void) |