aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/parport/parport_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/parport/parport_cs.c')
-rw-r--r--drivers/parport/parport_cs.c129
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
83typedef struct parport_info_t { 83typedef 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
90static void parport_detach(struct pcmcia_device *p_dev); 90static void parport_detach(struct pcmcia_device *p_dev);
91static void parport_config(dev_link_t *link); 91static int parport_config(struct pcmcia_device *link);
92static void parport_cs_release(dev_link_t *); 92static 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
102static int parport_attach(struct pcmcia_device *p_dev) 102static 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
141static void parport_detach(struct pcmcia_device *p_dev) 134static 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) \
162do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 152do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
163 153
164void parport_config(dev_link_t *link) 154static 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
255cs_failed: 233cs_failed:
256 cs_error(link->handle, last_fn, last_ret); 234 cs_error(link, last_fn, last_ret);
257failed: 235failed:
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
271void parport_cs_release(dev_link_t *link) 248void 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
297static 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);
308static 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
319static struct pcmcia_device_id parport_ids[] = { 264static 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
338static int __init init_parport_cs(void) 281static int __init init_parport_cs(void)