diff options
Diffstat (limited to 'drivers/scsi/pcmcia/qlogic_stub.c')
-rw-r--r-- | drivers/scsi/pcmcia/qlogic_stub.c | 127 |
1 files changed, 41 insertions, 86 deletions
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index dce7e687fd4a..86c2ac6ae623 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c | |||
@@ -91,18 +91,18 @@ static struct scsi_host_template qlogicfas_driver_template = { | |||
91 | /*====================================================================*/ | 91 | /*====================================================================*/ |
92 | 92 | ||
93 | typedef struct scsi_info_t { | 93 | typedef struct scsi_info_t { |
94 | dev_link_t link; | 94 | struct pcmcia_device *p_dev; |
95 | dev_node_t node; | 95 | dev_node_t node; |
96 | struct Scsi_Host *host; | 96 | struct Scsi_Host *host; |
97 | unsigned short manf_id; | 97 | unsigned short manf_id; |
98 | } scsi_info_t; | 98 | } scsi_info_t; |
99 | 99 | ||
100 | static void qlogic_release(dev_link_t *link); | 100 | static void qlogic_release(struct pcmcia_device *link); |
101 | static void qlogic_detach(struct pcmcia_device *p_dev); | 101 | static void qlogic_detach(struct pcmcia_device *p_dev); |
102 | static void qlogic_config(dev_link_t * link); | 102 | static int qlogic_config(struct pcmcia_device * link); |
103 | 103 | ||
104 | static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host, | 104 | static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host, |
105 | dev_link_t *link, int qbase, int qlirq) | 105 | struct pcmcia_device *link, int qbase, int qlirq) |
106 | { | 106 | { |
107 | int qltyp; /* type of chip */ | 107 | int qltyp; /* type of chip */ |
108 | int qinitid; | 108 | int qinitid; |
@@ -156,10 +156,9 @@ free_scsi_host: | |||
156 | err: | 156 | err: |
157 | return NULL; | 157 | return NULL; |
158 | } | 158 | } |
159 | static int qlogic_attach(struct pcmcia_device *p_dev) | 159 | static int qlogic_probe(struct pcmcia_device *link) |
160 | { | 160 | { |
161 | scsi_info_t *info; | 161 | scsi_info_t *info; |
162 | dev_link_t *link; | ||
163 | 162 | ||
164 | DEBUG(0, "qlogic_attach()\n"); | 163 | DEBUG(0, "qlogic_attach()\n"); |
165 | 164 | ||
@@ -168,7 +167,7 @@ static int qlogic_attach(struct pcmcia_device *p_dev) | |||
168 | if (!info) | 167 | if (!info) |
169 | return -ENOMEM; | 168 | return -ENOMEM; |
170 | memset(info, 0, sizeof(*info)); | 169 | memset(info, 0, sizeof(*info)); |
171 | link = &info->link; | 170 | info->p_dev = link; |
172 | link->priv = info; | 171 | link->priv = info; |
173 | link->io.NumPorts1 = 16; | 172 | link->io.NumPorts1 = 16; |
174 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | 173 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; |
@@ -176,30 +175,19 @@ static int qlogic_attach(struct pcmcia_device *p_dev) | |||
176 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 175 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
177 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 176 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
178 | link->conf.Attributes = CONF_ENABLE_IRQ; | 177 | link->conf.Attributes = CONF_ENABLE_IRQ; |
179 | link->conf.Vcc = 50; | ||
180 | link->conf.IntType = INT_MEMORY_AND_IO; | 178 | link->conf.IntType = INT_MEMORY_AND_IO; |
181 | link->conf.Present = PRESENT_OPTION; | 179 | link->conf.Present = PRESENT_OPTION; |
182 | 180 | ||
183 | link->handle = p_dev; | 181 | return qlogic_config(link); |
184 | p_dev->instance = link; | ||
185 | |||
186 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
187 | qlogic_config(link); | ||
188 | |||
189 | return 0; | ||
190 | } /* qlogic_attach */ | 182 | } /* qlogic_attach */ |
191 | 183 | ||
192 | /*====================================================================*/ | 184 | /*====================================================================*/ |
193 | 185 | ||
194 | static void qlogic_detach(struct pcmcia_device *p_dev) | 186 | static void qlogic_detach(struct pcmcia_device *link) |
195 | { | 187 | { |
196 | dev_link_t *link = dev_to_instance(p_dev); | ||
197 | |||
198 | DEBUG(0, "qlogic_detach(0x%p)\n", link); | 188 | DEBUG(0, "qlogic_detach(0x%p)\n", link); |
199 | 189 | ||
200 | if (link->state & DEV_CONFIG) | 190 | qlogic_release(link); |
201 | qlogic_release(link); | ||
202 | |||
203 | kfree(link->priv); | 191 | kfree(link->priv); |
204 | 192 | ||
205 | } /* qlogic_detach */ | 193 | } /* qlogic_detach */ |
@@ -209,9 +197,8 @@ static void qlogic_detach(struct pcmcia_device *p_dev) | |||
209 | #define CS_CHECK(fn, ret) \ | 197 | #define CS_CHECK(fn, ret) \ |
210 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 198 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
211 | 199 | ||
212 | static void qlogic_config(dev_link_t * link) | 200 | static int qlogic_config(struct pcmcia_device * link) |
213 | { | 201 | { |
214 | client_handle_t handle = link->handle; | ||
215 | scsi_info_t *info = link->priv; | 202 | scsi_info_t *info = link->priv; |
216 | tuple_t tuple; | 203 | tuple_t tuple; |
217 | cisparse_t parse; | 204 | cisparse_t parse; |
@@ -225,38 +212,35 @@ static void qlogic_config(dev_link_t * link) | |||
225 | tuple.TupleDataMax = 64; | 212 | tuple.TupleDataMax = 64; |
226 | tuple.TupleOffset = 0; | 213 | tuple.TupleOffset = 0; |
227 | tuple.DesiredTuple = CISTPL_CONFIG; | 214 | tuple.DesiredTuple = CISTPL_CONFIG; |
228 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 215 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
229 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 216 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
230 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 217 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
231 | link->conf.ConfigBase = parse.config.base; | 218 | link->conf.ConfigBase = parse.config.base; |
232 | 219 | ||
233 | tuple.DesiredTuple = CISTPL_MANFID; | 220 | tuple.DesiredTuple = CISTPL_MANFID; |
234 | if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) | 221 | if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) |
235 | info->manf_id = le16_to_cpu(tuple.TupleData[0]); | 222 | info->manf_id = le16_to_cpu(tuple.TupleData[0]); |
236 | 223 | ||
237 | /* Configure card */ | ||
238 | link->state |= DEV_CONFIG; | ||
239 | |||
240 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 224 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
241 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 225 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
242 | while (1) { | 226 | while (1) { |
243 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 || | 227 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || |
244 | pcmcia_parse_tuple(handle, &tuple, &parse) != 0) | 228 | pcmcia_parse_tuple(link, &tuple, &parse) != 0) |
245 | goto next_entry; | 229 | goto next_entry; |
246 | link->conf.ConfigIndex = parse.cftable_entry.index; | 230 | link->conf.ConfigIndex = parse.cftable_entry.index; |
247 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; | 231 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; |
248 | link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; | 232 | link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; |
249 | if (link->io.BasePort1 != 0) { | 233 | if (link->io.BasePort1 != 0) { |
250 | i = pcmcia_request_io(handle, &link->io); | 234 | i = pcmcia_request_io(link, &link->io); |
251 | if (i == CS_SUCCESS) | 235 | if (i == CS_SUCCESS) |
252 | break; | 236 | break; |
253 | } | 237 | } |
254 | next_entry: | 238 | next_entry: |
255 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); | 239 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); |
256 | } | 240 | } |
257 | 241 | ||
258 | CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); | 242 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
259 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); | 243 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
260 | 244 | ||
261 | if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { | 245 | if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { |
262 | /* set ATAcmd */ | 246 | /* set ATAcmd */ |
@@ -275,82 +259,54 @@ static void qlogic_config(dev_link_t * link) | |||
275 | 259 | ||
276 | if (!host) { | 260 | if (!host) { |
277 | printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name); | 261 | printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name); |
278 | goto out; | 262 | goto cs_failed; |
279 | } | 263 | } |
280 | 264 | ||
281 | sprintf(info->node.dev_name, "scsi%d", host->host_no); | 265 | sprintf(info->node.dev_name, "scsi%d", host->host_no); |
282 | link->dev = &info->node; | 266 | link->dev_node = &info->node; |
283 | info->host = host; | 267 | info->host = host; |
284 | 268 | ||
285 | out: | 269 | return 0; |
286 | link->state &= ~DEV_CONFIG_PENDING; | ||
287 | return; | ||
288 | 270 | ||
289 | cs_failed: | 271 | cs_failed: |
290 | cs_error(link->handle, last_fn, last_ret); | 272 | cs_error(link, last_fn, last_ret); |
291 | link->dev = NULL; | 273 | pcmcia_disable_device(link); |
292 | pcmcia_release_configuration(link->handle); | 274 | return -ENODEV; |
293 | pcmcia_release_io(link->handle, &link->io); | ||
294 | pcmcia_release_irq(link->handle, &link->irq); | ||
295 | link->state &= ~DEV_CONFIG; | ||
296 | return; | ||
297 | 275 | ||
298 | } /* qlogic_config */ | 276 | } /* qlogic_config */ |
299 | 277 | ||
300 | /*====================================================================*/ | 278 | /*====================================================================*/ |
301 | 279 | ||
302 | static void qlogic_release(dev_link_t *link) | 280 | static void qlogic_release(struct pcmcia_device *link) |
303 | { | 281 | { |
304 | scsi_info_t *info = link->priv; | 282 | scsi_info_t *info = link->priv; |
305 | 283 | ||
306 | DEBUG(0, "qlogic_release(0x%p)\n", link); | 284 | DEBUG(0, "qlogic_release(0x%p)\n", link); |
307 | 285 | ||
308 | scsi_remove_host(info->host); | 286 | scsi_remove_host(info->host); |
309 | link->dev = NULL; | ||
310 | 287 | ||
311 | free_irq(link->irq.AssignedIRQ, info->host); | 288 | free_irq(link->irq.AssignedIRQ, info->host); |
312 | 289 | pcmcia_disable_device(link); | |
313 | pcmcia_release_configuration(link->handle); | ||
314 | pcmcia_release_io(link->handle, &link->io); | ||
315 | pcmcia_release_irq(link->handle, &link->irq); | ||
316 | 290 | ||
317 | scsi_host_put(info->host); | 291 | scsi_host_put(info->host); |
318 | |||
319 | link->state &= ~DEV_CONFIG; | ||
320 | } | 292 | } |
321 | 293 | ||
322 | /*====================================================================*/ | 294 | /*====================================================================*/ |
323 | 295 | ||
324 | static int qlogic_suspend(struct pcmcia_device *dev) | 296 | static int qlogic_resume(struct pcmcia_device *link) |
325 | { | 297 | { |
326 | dev_link_t *link = dev_to_instance(dev); | 298 | scsi_info_t *info = link->priv; |
327 | |||
328 | link->state |= DEV_SUSPEND; | ||
329 | if (link->state & DEV_CONFIG) | ||
330 | pcmcia_release_configuration(link->handle); | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | 299 | ||
335 | static int qlogic_resume(struct pcmcia_device *dev) | 300 | pcmcia_request_configuration(link, &link->conf); |
336 | { | 301 | if ((info->manf_id == MANFID_MACNICA) || |
337 | dev_link_t *link = dev_to_instance(dev); | 302 | (info->manf_id == MANFID_PIONEER) || |
338 | 303 | (info->manf_id == 0x0098)) { | |
339 | link->state &= ~DEV_SUSPEND; | 304 | outb(0x80, link->io.BasePort1 + 0xd); |
340 | if (link->state & DEV_CONFIG) { | 305 | outb(0x24, link->io.BasePort1 + 0x9); |
341 | scsi_info_t *info = link->priv; | 306 | outb(0x04, link->io.BasePort1 + 0xd); |
342 | |||
343 | pcmcia_request_configuration(link->handle, &link->conf); | ||
344 | if ((info->manf_id == MANFID_MACNICA) || | ||
345 | (info->manf_id == MANFID_PIONEER) || | ||
346 | (info->manf_id == 0x0098)) { | ||
347 | outb(0x80, link->io.BasePort1 + 0xd); | ||
348 | outb(0x24, link->io.BasePort1 + 0x9); | ||
349 | outb(0x04, link->io.BasePort1 + 0xd); | ||
350 | } | ||
351 | /* Ugggglllyyyy!!! */ | ||
352 | qlogicfas408_bus_reset(NULL); | ||
353 | } | 307 | } |
308 | /* Ugggglllyyyy!!! */ | ||
309 | qlogicfas408_bus_reset(NULL); | ||
354 | 310 | ||
355 | return 0; | 311 | return 0; |
356 | } | 312 | } |
@@ -382,10 +338,9 @@ static struct pcmcia_driver qlogic_cs_driver = { | |||
382 | .drv = { | 338 | .drv = { |
383 | .name = "qlogic_cs", | 339 | .name = "qlogic_cs", |
384 | }, | 340 | }, |
385 | .probe = qlogic_attach, | 341 | .probe = qlogic_probe, |
386 | .remove = qlogic_detach, | 342 | .remove = qlogic_detach, |
387 | .id_table = qlogic_ids, | 343 | .id_table = qlogic_ids, |
388 | .suspend = qlogic_suspend, | ||
389 | .resume = qlogic_resume, | 344 | .resume = qlogic_resume, |
390 | }; | 345 | }; |
391 | 346 | ||