1 /* 2 * PCMCIA 16-bit resource management functions 3 * 4 * The initial developer of the original code is David A. Hinds 5 * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds 6 * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. 7 * 8 * Copyright (C) 1999 David A. Hinds 9 * Copyright (C) 2004-2005 Dominik Brodowski 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 * 15 */ 16 17 #include <linux/module.h> 18 #include <linux/kernel.h> 19 #include <linux/interrupt.h> 20 #include <linux/delay.h> 21 #include <linux/pci.h> 22 #include <linux/device.h> 23 24 #include <pcmcia/cs_types.h> 25 #include <pcmcia/ss.h> 26 #include <pcmcia/cs.h> 27 #include <pcmcia/cistpl.h> 28 #include <pcmcia/cisreg.h> 29 #include <pcmcia/ds.h> 30 31 #include "cs_internal.h" 32 #include "ds_internal.h" 33 34 35 /* Access speed for IO windows */ 36 static int io_speed = 0; 37 module_param(io_speed, int, 0444); 38 39 40 #ifdef CONFIG_PCMCIA_PROBE 41 #include <asm/irq.h> 42 /* mask of IRQs already reserved by other cards, we should avoid using them */ 43 static u8 pcmcia_used_irq[NR_IRQS]; 44 #endif 45 46 47 #ifdef DEBUG 48 extern int ds_pc_debug; 49 50 #define ds_dbg(skt, lvl, fmt, arg...) do { \ 51 if (ds_pc_debug >= lvl) \ 52 printk(KERN_DEBUG "pcmcia_resource: %s: " fmt, \ 53 cs_socket_name(skt) , ## arg); \ 54 } while (0) 55 #else 56 #define ds_dbg(lvl, fmt, arg...) do { } while (0) 57 #endif 58 59 60 61 /** alloc_io_space 62 * 63 * Special stuff for managing IO windows, because they are scarce 64 */ 65 66 static int alloc_io_space(struct pcmcia_socket *s, u_int attr, 67 unsigned int *base, unsigned int num, u_int lines) 68 { 69 int i; 70 unsigned int try, align; 71 72 align = (*base) ? (lines ? 1<<lines : 0) : 1; 73 if (align && (align < num)) { 74 if (*base) { 75 ds_dbg(s, 0, "odd IO request: num %#x align %#x\n", 76 num, align); 77 align = 0; 78 } else 79 while (align && (align < num)) align <<= 1; 80 } 81 if (*base & ~(align-1)) { 82 ds_dbg(s, 0, "odd IO request: base %#x align %#x\n", 83 *base, align); 84 align = 0; 85 } 86 if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) { 87 *base = s->io_offset | (*base & 0x0fff); 88 return 0; 89 } 90 /* Check for an already-allocated window that must conflict with 91 * what was asked for. It is a hack because it does not catch all 92 * potential conflicts, just the most obvious ones. 93 */ 94 for (i = 0; i < MAX_IO_WIN; i++) 95 if ((s->io[i].res) && *base && 96 ((s->io[i].res->start & (align-1)) == *base)) 97 return 1; 98 for (i = 0; i < MAX_IO_WIN; i++) { 99 if (!s->io[i].res) { 100 s->io[i].res = pcmcia_find_io_region(*base, num, align, s); 101 if (s->io[i].res) { 102 *base = s->io[i].res->start; 103 s->io[i].res->flags = (s->io[i].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS); 104 s->io[i].InUse = num; 105 break; 106 } else 107 return 1; 108 } else if ((s->io[i].res->flags & IORESOURCE_BITS) != (attr & IORESOURCE_BITS)) 109 continue; 110 /* Try to extend top of window */ 111 try = s->io[i].res->end + 1; 112 if ((*base == 0) || (*base == try)) 113 if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start, 114 s->io[i].res->end + num, s) == 0) { 115 *base = try; 116 s->io[i].InUse += num; 117 break; 118 } 119 /* Try to extend bottom of window */ 120 try = s->io[i].res->start - num; 121 if ((*base == 0) || (*base == try)) 122 if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num, 123 s->io[i].res->end, s) == 0) { 124 *base = try; 125 s->io[i].InUse += num; 126 break; 127 } 128 } 129 return (i == MAX_IO_WIN); 130 } /* alloc_io_space */ 131 132 133 static void release_io_space(struct pcmcia_socket *s, unsigned int base, 134 unsigned int num) 135 { 136 int i; 137 138 for (i = 0; i < MAX_IO_WIN; i++) { 139 if (!s->io[i].res) 140 continue; 141 if ((s->io[i].res->start <= base) && 142 (s->io[i].res->end >= base+num-1)) { 143 s->io[i].InUse -= num; 144 /* Free the window if no one else is using it */ 145 if (s->io[i].InUse == 0) { 146 release_resource(s->io[i].res); 147 kfree(s->io[i].res); 148 s->io[i].res = NULL; 149 } 150 } 151 } 152 } /* release_io_space */ 153 154 155 /** pccard_access_configuration_register 156 * 157 * Access_configuration_register() reads and writes configuration 158 * registers in attribute memory. Memory window 0 is reserved for 159 * this and the tuple reading services. 160 */ 161 162 int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, 163 conf_reg_t *reg) 164 { 165 struct pcmcia_socket *s; 166 config_t *c; 167 int addr; 168 u_char val; 169 170 if (!p_dev || !p_dev->function_config) 171 return CS_NO_CARD; 172 173 s = p_dev->socket; 174 c = p_dev->function_config; 175 176 if (!(c->state & CONFIG_LOCKED)) 177 return CS_CONFIGURATION_LOCKED; 178 179 addr = (c->ConfigBase + reg->Offset) >> 1; 180 181 switch (reg->Action) { 182 case CS_READ: 183 pcmcia_read_cis_mem(s, 1, addr, 1, &val); 184 reg->Value = val; 185 break; 186 case CS_WRITE: 187 val = reg->Value; 188 pcmcia_write_cis_mem(s, 1, addr, 1, &val); 189 break; 190 default: 191 return CS_BAD_ARGS; 192 break; 193 } 194 return CS_SUCCESS; 195 } /* pcmcia_access_configuration_register */ 196 EXPORT_SYMBOL(pcmcia_access_configuration_register); 197 198 199 int pccard_get_configuration_info(struct pcmcia_socket *s, 200 struct pcmcia_device *p_dev, 201 config_info_t *config) 202 { 203 config_t *c; 204 205 if (!(s->state & SOCKET_PRESENT)) 206 return CS_NO_CARD; 207 208 209 #ifdef CONFIG_CARDBUS 210 if (s->state & SOCKET_CARDBUS) { 211 memset(config, 0, sizeof(config_info_t)); 212 config->Vcc = s->socket.Vcc; 213 config->Vpp1 = config->Vpp2 = s->socket.Vpp; 214 config->Option = s->cb_dev->subordinate->number; 215 if (s->state & SOCKET_CARDBUS_CONFIG) { 216 config->Attributes = CONF_VALID_CLIENT; 217 config->IntType = INT_CARDBUS; 218 config->AssignedIRQ = s->irq.AssignedIRQ; 219 if (config->AssignedIRQ) 220 config->Attributes |= CONF_ENABLE_IRQ; 221 if (s->io[0].res) { 222 config->BasePort1 = s->io[0].res->start; 223 config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1; 224 } 225 } 226 return CS_SUCCESS; 227 } 228 #endif 229 230 if (p_dev) { 231 c = p_dev->function_config; 232 config->Function = p_dev->func; 233 } else { 234 c = NULL; 235 config->Function = 0; 236 } 237 238 if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { 239 config->Attributes = 0; 240 config->Vcc = s->socket.Vcc; 241 config->Vpp1 = config->Vpp2 = s->socket.Vpp; 242 return CS_SUCCESS; 243 } 244 245 config->Attributes = c->Attributes | CONF_VALID_CLIENT; 246 config->Vcc = s->socket.Vcc; 247 config->Vpp1 = config->Vpp2 = s->socket.Vpp; 248 config->IntType = c->IntType; 249 config->ConfigBase = c->ConfigBase; 250 config->Status = c->Status; 251 config->Pin = c->Pin; 252 config->Copy = c->Copy; 253 config->Option = c->Option; 254 config->ExtStatus = c->ExtStatus; 255 config->Present = config->CardValues = c->CardValues; 256 config->IRQAttributes = c->irq.Attributes; 257 config->AssignedIRQ = s->irq.AssignedIRQ; 258 config->BasePort1 = c->io.BasePort1; 259 config->NumPorts1 = c->io.NumPorts1; 260 config->Attributes1 = c->io.Attributes1; 261 config->BasePort2 = c->io.BasePort2; 262 config->NumPorts2 = c->io.NumPorts2; 263 config->Attributes2 = c->io.Attributes2; 264 config->IOAddrLines = c->io.IOAddrLines; 265 266 return CS_SUCCESS; 267 } /* pccard_get_configuration_info */ 268 269 int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, 270 config_info_t *config) 271 { 272 return pccard_get_configuration_info(p_dev->socket, p_dev, 273 config); 274 } 275 EXPORT_SYMBOL(pcmcia_get_configuration_info); 276 277 278 /** pcmcia_get_window 279 */ 280 int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, 281 int idx, win_req_t *req) 282 { 283 window_t *win; 284 int w; 285 286 if (!s || !(s->state & SOCKET_PRESENT)) 287 return CS_NO_CARD; 288 for (w = idx; w < MAX_WIN; w++) 289 if (s->state & SOCKET_WIN_REQ(w)) 290 break; 291 if (w == MAX_WIN) 292 return CS_NO_MORE_ITEMS; 293 win = &s->win[w]; 294 req->Base = win->ctl.res->start; 295 req->Size = win->ctl.res->end - win->ctl.res->start + 1; 296 req->AccessSpeed = win->ctl.speed; 297 req->Attributes = 0; 298 if (win->ctl.flags & MAP_ATTRIB) 299 req->Attributes |= WIN_MEMORY_TYPE_AM; 300 if (win->ctl.flags & MAP_ACTIVE) 301 req->Attributes |= WIN_ENABLE; 302 if (win->ctl.flags & MAP_16BIT) 303 req->Attributes |= WIN_DATA_WIDTH_16; 304 if (win->ctl.flags & MAP_USE_WAIT) 305 req->Attributes |= WIN_USE_WAIT; 306 *handle = win; 307 return CS_SUCCESS; 308 } /* pcmcia_get_window */ 309 EXPORT_SYMBOL(pcmcia_get_window); 310 311 312 /** pcmcia_get_mem_page 313 * 314 * Change the card address of an already open memory window. 315 */ 316 int pcmcia_get_mem_page(window_handle_t win, memreq_t *req) 317 { 318 if ((win == NULL) || (win->magic != WINDOW_MAGIC)) 319 return CS_BAD_HANDLE; 320 req->Page = 0; 321 req->CardOffset = win->ctl.card_start; 322 return CS_SUCCESS; 323 } /* pcmcia_get_mem_page */ 324 EXPORT_SYMBOL(pcmcia_get_mem_page); 325 326 327 int pcmcia_map_mem_page(window_handle_t win, memreq_t *req) 328 { 329 struct pcmcia_socket *s; 330 if ((win == NULL) || (win->magic != WINDOW_MAGIC)) 331 return CS_BAD_HANDLE; 332 if (req->Page != 0) 333 return CS_BAD_PAGE; 334 s = win->sock; 335 win->ctl.card_start = req->CardOffset; 336 if (s->ops->set_mem_map(s, &win->ctl) != 0) 337 return CS_BAD_OFFSET; 338 return CS_SUCCESS; 339 } /* pcmcia_map_mem_page */ 340 EXPORT_SYMBOL(pcmcia_map_mem_page); 341 342 343 /** pcmcia_modify_configuration 344 * 345 * Modify a locked socket configuration 346 */ 347 int pcmcia_modify_configuration(struct pcmcia_device *p_dev, 348 modconf_t *mod) 349 { 350 struct pcmcia_socket *s; 351 config_t *c; 352 353 s = p_dev->socket; 354 c = p_dev->function_config; 355 356 if (!(s->state & SOCKET_PRESENT)) 357 return CS_NO_CARD; 358 if (!(c->state & CONFIG_LOCKED)) 359 return CS_CONFIGURATION_LOCKED; 360 361 if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { 362 if (mod->Attributes & CONF_ENABLE_IRQ) { 363 c->Attributes |= CONF_ENABLE_IRQ; 364 s->socket.io_irq = s->irq.AssignedIRQ; 365 } else { 366 c->Attributes &= ~CONF_ENABLE_IRQ; 367 s->socket.io_irq = 0; 368 } 369 s->ops->set_socket(s, &s->socket); 370 } 371 372 if (mod->Attributes & CONF_VCC_CHANGE_VALID) 373 return CS_BAD_VCC; 374 375 /* We only allow changing Vpp1 and Vpp2 to the same value */ 376 if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && 377 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { 378 if (mod->Vpp1 != mod->Vpp2) 379 return CS_BAD_VPP; 380 s->socket.Vpp = mod->Vpp1; 381 if (s->ops->set_socket(s, &s->socket)) 382 return CS_BAD_VPP; 383 } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || 384 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) 385 return CS_BAD_VPP; 386 387 if (mod->Attributes & CONF_IO_CHANGE_WIDTH) { 388 pccard_io_map io_off = { 0, 0, 0, 0, 1 }; 389 pccard_io_map io_on; 390 int i; 391 392 io_on.speed = io_speed; 393 for (i = 0; i < MAX_IO_WIN; i++) { 394 if (!s->io[i].res) 395 continue; 396 io_off.map = i; 397 io_on.map = i; 398 399 io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8; 400 io_on.start = s->io[i].res->start; 401 io_on.stop = s->io[i].res->end; 402 403 s->ops->set_io_map(s, &io_off); 404 mdelay(40); 405 s->ops->set_io_map(s, &io_on); 406 } 407 } 408 409 return CS_SUCCESS; 410 } /* modify_configuration */ 411 EXPORT_SYMBOL(pcmcia_modify_configuration); 412 413 414 int pcmcia_release_configuration(struct pcmcia_device *p_dev) 415 { 416 pccard_io_map io = { 0, 0, 0, 0, 1 }; 417 struct pcmcia_socket *s = p_dev->socket; 418 config_t *c = p_dev->function_config; 419 int i; 420 421 if (p_dev->_locked) { 422 p_dev->_locked = 0; 423 if (--(s->lock_count) == 0) { 424 s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ 425 s->socket.Vpp = 0; 426 s->socket.io_irq = 0; 427 s->ops->set_socket(s, &s->socket); 428 } 429 } 430 if (c->state & CONFIG_LOCKED) { 431 c->state &= ~CONFIG_LOCKED; 432 if (c->state & CONFIG_IO_REQ) 433 for (i = 0; i < MAX_IO_WIN; i++) { 434 if (!s->io[i].res) 435 continue; 436 s->io[i].Config--; 437 if (s->io[i].Config != 0) 438 continue; 439 io.map = i; 440 s->ops->set_io_map(s, &io); 441 } 442 } 443 444 return CS_SUCCESS; 445 } /* pcmcia_release_configuration */ 446 447 448 /** pcmcia_release_io 449 * 450 * Release_io() releases the I/O ranges allocated by a client. This 451 * may be invoked some time after a card ejection has already dumped 452 * the actual socket configuration, so if the client is "stale", we 453 * don't bother checking the port ranges against the current socket 454 * values. 455 */ 456 static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) 457 { 458 struct pcmcia_socket *s = p_dev->socket; 459 config_t *c = p_dev->function_config; 460 461 if (!p_dev->_io ) 462 return CS_BAD_HANDLE; 463 464 p_dev->_io = 0; 465 466 if ((c->io.BasePort1 != req->BasePort1) || 467 (c->io.NumPorts1 != req->NumPorts1) || 468 (c->io.BasePort2 != req->BasePort2) || 469 (c->io.NumPorts2 != req->NumPorts2)) 470 return CS_BAD_ARGS; 471 472 c->state &= ~CONFIG_IO_REQ; 473 474 release_io_space(s, req->BasePort1, req->NumPorts1); 475 if (req->NumPorts2) 476 release_io_space(s, req->BasePort2, req->NumPorts2); 477 478 return CS_SUCCESS; 479 } /* pcmcia_release_io */ 480 481 482 static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) 483 { 484 struct pcmcia_socket *s = p_dev->socket; 485 config_t *c= p_dev->function_config; 486 487 if (!p_dev->_irq) 488 return CS_BAD_HANDLE; 489 p_dev->_irq = 0; 490 491 if (c->state & CONFIG_LOCKED) 492 return CS_CONFIGURATION_LOCKED; 493 if (c->irq.Attributes != req->Attributes) 494 return CS_BAD_ATTRIBUTE; 495 if (s->irq.AssignedIRQ != req->AssignedIRQ) 496 return CS_BAD_IRQ; 497 if (--s->irq.Config == 0) { 498 c->state &= ~CONFIG_IRQ_REQ; 499 s->irq.AssignedIRQ = 0; 500 } 501 502 if (req->Attributes & IRQ_HANDLE_PRESENT) { 503 free_irq(req->AssignedIRQ, req->Instance); 504 } 505 506 #ifdef CONFIG_PCMCIA_PROBE 507 pcmcia_used_irq[req->AssignedIRQ]--; 508 #endif 509 510 return CS_SUCCESS; 511 } /* pcmcia_release_irq */ 512 513 514 int pcmcia_release_window(window_handle_t win) 515 { 516 struct pcmcia_socket *s; 517 518 if ((win == NULL) || (win->magic != WINDOW_MAGIC)) 519 return CS_BAD_HANDLE; 520 s = win->sock; 521 if (!(win->handle->_win & CLIENT_WIN_REQ(win->index))) 522 return CS_BAD_HANDLE; 523 524 /* Shut down memory window */ 525 win->ctl.flags &= ~MAP_ACTIVE; 526 s->ops->set_mem_map(s, &win->ctl); 527 s->state &= ~SOCKET_WIN_REQ(win->index); 528 529 /* Release system memory */ 530 if (win->ctl.res) { 531 release_resource(win->ctl.res); 532 kfree(win->ctl.res); 533 win->ctl.res = NULL; 534 } 535 win->handle->_win &= ~CLIENT_WIN_REQ(win->index); 536 537 win->magic = 0; 538 539 return CS_SUCCESS; 540 } /* pcmcia_release_window */ 541 EXPORT_SYMBOL(pcmcia_release_window); 542 543 544 int pcmcia_request_configuration(struct pcmcia_device *p_dev, 545 config_req_t *req) 546 { 547 int i; 548 u_int base; 549 struct pcmcia_socket *s = p_dev->socket; 550 config_t *c; 551 pccard_io_map iomap; 552 553 if (!(s->state & SOCKET_PRESENT)) 554 return CS_NO_CARD; 555 556 if (req->IntType & INT_CARDBUS) 557 return CS_UNSUPPORTED_MODE; 558 c = p_dev->function_config; 559 if (c->state & CONFIG_LOCKED) 560 return CS_CONFIGURATION_LOCKED; 561 562 /* Do power control. We don't allow changes in Vcc. */ 563 s->socket.Vpp = req->Vpp; 564 if (s->ops->set_socket(s, &s->socket)) 565 return CS_BAD_VPP; 566 567 /* Pick memory or I/O card, DMA mode, interrupt */ 568 c->IntType = req->IntType; 569 c->Attributes = req->Attributes; 570 if (req->IntType & INT_MEMORY_AND_IO) 571 s->socket.flags |= SS_IOCARD; 572 if (req->IntType & INT_ZOOMED_VIDEO) 573 s->socket.flags |= SS_ZVCARD | SS_IOCARD; 574 if (req->Attributes & CONF_ENABLE_DMA) 575 s->socket.flags |= SS_DMA_MODE; 576 if (req->Attributes & CONF_ENABLE_SPKR) 577 s->socket.flags |= SS_SPKR_ENA; 578 if (req->Attributes & CONF_ENABLE_IRQ) 579 s->socket.io_irq = s->irq.AssignedIRQ; 580 else 581 s->socket.io_irq = 0; 582 s->ops->set_socket(s, &s->socket); 583 s->lock_count++; 584 585 /* Set up CIS configuration registers */ 586 base = c->ConfigBase = req->ConfigBase; 587 c->CardValues = req->Present; 588 if (req->Present & PRESENT_COPY) { 589 c->Copy = req->Copy; 590 pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy); 591 } 592 if (req->Present & PRESENT_OPTION) { 593 if (s->functions == 1) { 594 c->Option = req->ConfigIndex & COR_CONFIG_MASK; 595 } else { 596 c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK; 597 c->Option |= COR_FUNC_ENA|COR_IREQ_ENA; 598 if (req->Present & PRESENT_IOBASE_0) 599 c->Option |= COR_ADDR_DECODE; 600 } 601 if (c->state & CONFIG_IRQ_REQ) 602 if (!(c->irq.Attributes & IRQ_FORCED_PULSE)) 603 c->Option |= COR_LEVEL_REQ; 604 pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option); 605 mdelay(40); 606 } 607 if (req->Present & PRESENT_STATUS) { 608 c->Status = req->Status; 609 pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status); 610 } 611 if (req->Present & PRESENT_PIN_REPLACE) { 612 c->Pin = req->Pin; 613 pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin); 614 } 615 if (req->Present & PRESENT_EXT_STATUS) { 616 c->ExtStatus = req->ExtStatus; 617 pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus); 618 } 619 if (req->Present & PRESENT_IOBASE_0) { 620 u_char b = c->io.BasePort1 & 0xff; 621 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b); 622 b = (c->io.BasePort1 >> 8) & 0xff; 623 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b); 624 } 625 if (req->Present & PRESENT_IOSIZE) { 626 u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1; 627 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b); 628 } 629 630 /* Configure I/O windows */ 631 if (c->state & CONFIG_IO_REQ) { 632 iomap.speed = io_speed; 633 for (i = 0; i < MAX_IO_WIN; i++) 634 if (s->io[i].res) { 635 iomap.map = i; 636 iomap.flags = MAP_ACTIVE; 637 switch (s->io[i].res->flags & IO_DATA_PATH_WIDTH) { 638 case IO_DATA_PATH_WIDTH_16: 639 iomap.flags |= MAP_16BIT; break; 640 case IO_DATA_PATH_WIDTH_AUTO: 641 iomap.flags |= MAP_AUTOSZ; break; 642 default: 643 break; 644 } 645 iomap.start = s->io[i].res->start; 646 iomap.stop = s->io[i].res->end; 647 s->ops->set_io_map(s, &iomap); 648 s->io[i].Config++; 649 } 650 } 651 652 c->state |= CONFIG_LOCKED; 653 p_dev->_locked = 1; 654 return CS_SUCCESS; 655 } /* pcmcia_request_configuration */ 656 EXPORT_SYMBOL(pcmcia_request_configuration); 657 658 659 /** pcmcia_request_io 660 * 661 * Request_io() reserves ranges of port addresses for a socket. 662 * I have not implemented range sharing or alias addressing. 663 */ 664 int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) 665 { 666 struct pcmcia_socket *s = p_dev->socket; 667 config_t *c; 668 669 if (!(s->state & SOCKET_PRESENT)) 670 return CS_NO_CARD; 671 672 if (!req) 673 return CS_UNSUPPORTED_MODE; 674 c = p_dev->function_config; 675 if (c->state & CONFIG_LOCKED) 676 return CS_CONFIGURATION_LOCKED; 677 if (c->state & CONFIG_IO_REQ) 678 return CS_IN_USE; 679 if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) 680 return CS_BAD_ATTRIBUTE; 681 if ((req->NumPorts2 > 0) && 682 (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) 683 return CS_BAD_ATTRIBUTE; 684 685 if (alloc_io_space(s, req->Attributes1, &req->BasePort1, 686 req->NumPorts1, req->IOAddrLines)) 687 return CS_IN_USE; 688 689 if (req->NumPorts2) { 690 if (alloc_io_space(s, req->Attributes2, &req->BasePort2, 691 req->NumPorts2, req->IOAddrLines)) { 692 release_io_space(s, req->BasePort1, req->NumPorts1); 693 return CS_IN_USE; 694 } 695 } 696 697 c->io = *req; 698 c->state |= CONFIG_IO_REQ; 699 p_dev->_io = 1; 700 return CS_SUCCESS; 701 } /* pcmcia_request_io */ 702 EXPORT_SYMBOL(pcmcia_request_io); 703 704 705 /** pcmcia_request_irq 706 * 707 * Request_irq() reserves an irq for this client. 708 * 709 * Also, since Linux only reserves irq's when they are actually 710 * hooked, we don't guarantee that an irq will still be available 711 * when the configuration is locked. Now that I think about it, 712 * there might be a way to fix this using a dummy handler. 713 */ 714 715 #ifdef CONFIG_PCMCIA_PROBE 716 static irqreturn_t test_action(int cpl, void *dev_id) 717 { 718 return IRQ_NONE; 719 } 720 #endif 721 722 int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) 723 { 724 struct pcmcia_socket *s = p_dev->socket; 725 config_t *c; 726 int ret = CS_IN_USE, irq = 0; 727 int type; 728 729 if (!(s->state & SOCKET_PRESENT)) 730 return CS_NO_CARD; 731 c = p_dev->function_config; 732 if (c->state & CONFIG_LOCKED) 733 return CS_CONFIGURATION_LOCKED; 734 if (c->state & CONFIG_IRQ_REQ) 735 return CS_IN_USE; 736 737 /* Decide what type of interrupt we are registering */ 738 type = 0; 739 if (s->functions > 1) /* All of this ought to be handled higher up */ 740 type = IRQF_SHARED; 741 if (req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) 742 type = IRQF_SHARED; 743 744 #ifdef CONFIG_PCMCIA_PROBE 745 746 #ifdef IRQ_NOAUTOEN 747 /* if the underlying IRQ infrastructure allows for it, only allocate 748 * the IRQ, but do not enable it 749 */ 750 if (!(req->Attributes & IRQ_HANDLE_PRESENT)) 751 type |= IRQ_NOAUTOEN; 752 #endif /* IRQ_NOAUTOEN */ 753 754 if (s->irq.AssignedIRQ != 0) { 755 /* If the interrupt is already assigned, it must be the same */ 756 irq = s->irq.AssignedIRQ; 757 } else { 758 int try; 759 u32 mask = s->irq_mask; 760 void *data = &p_dev->dev.driver; /* something unique to this device */ 761 762 for (try = 0; try < 64; try++) { 763 irq = try % 32; 764 765 /* marked as available by driver, and not blocked by userspace? */ 766 if (!((mask >> irq) & 1)) 767 continue; 768 769 /* avoid an IRQ which is already used by a PCMCIA card */ 770 if ((try < 32) && pcmcia_used_irq[irq]) 771 continue; 772 773 /* register the correct driver, if possible, of check whether 774 * registering a dummy handle works, i.e. if the IRQ isn't 775 * marked as used by the kernel resource management core */ 776 ret = request_irq(irq, 777 (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action, 778 type, 779 p_dev->devname, 780 (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data); 781 if (!ret) { 782 if (!(req->Attributes & IRQ_HANDLE_PRESENT)) 783 free_irq(irq, data); 784 break; 785 } 786 } 787 } 788 #endif 789 /* only assign PCI irq if no IRQ already assigned */ 790 if (ret && !s->irq.AssignedIRQ) { 791 if (!s->pci_irq) 792 return ret; 793 type = IRQF_SHARED; 794 irq = s->pci_irq; 795 } 796 797 if (ret && (req->Attributes & IRQ_HANDLE_PRESENT)) { 798 if (request_irq(irq, req->Handler, type, p_dev->devname, req->Instance)) 799 return CS_IN_USE; 800 } 801 802 /* Make sure the fact the request type was overridden is passed back */ 803 if (type == IRQF_SHARED && !(req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)) { 804 req->Attributes |= IRQ_TYPE_DYNAMIC_SHARING; 805 printk(KERN_WARNING "pcmcia: request for exclusive IRQ could not be fulfilled.\n"); 806 printk(KERN_WARNING "pcmcia: the driver needs updating to supported shared IRQ lines.\n"); 807 } 808 c->irq.Attributes = req->Attributes; 809 s->irq.AssignedIRQ = req->AssignedIRQ = irq; 810 s->irq.Config++; 811 812 c->state |= CONFIG_IRQ_REQ; 813 p_dev->_irq = 1; 814 815 #ifdef CONFIG_PCMCIA_PROBE 816 pcmcia_used_irq[irq]++; 817 #endif 818 819 return CS_SUCCESS; 820 } /* pcmcia_request_irq */ 821 EXPORT_SYMBOL(pcmcia_request_irq); 822 823 824 /** pcmcia_request_window 825 * 826 * Request_window() establishes a mapping between card memory space 827 * and system memory space. 828 */ 829 int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh) 830 { 831 struct pcmcia_socket *s = (*p_dev)->socket; 832 window_t *win; 833 u_long align; 834 int w; 835 836 if (!(s->state & SOCKET_PRESENT)) 837 return CS_NO_CARD; 838 if (req->Attributes & (WIN_PAGED | WIN_SHARED)) 839 return CS_BAD_ATTRIBUTE; 840 841 /* Window size defaults to smallest available */ 842 if (req->Size == 0) 843 req->Size = s->map_size; 844 align = (((s->features & SS_CAP_MEM_ALIGN) || 845 (req->Attributes & WIN_STRICT_ALIGN)) ? 846 req->Size : s->map_size); 847 if (req->Size & (s->map_size-1)) 848 return CS_BAD_SIZE; 849 if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || 850 (req->Base & (align-1))) 851 return CS_BAD_BASE; 852 if (req->Base) 853 align = 0; 854 855 /* Allocate system memory window */ 856 for (w = 0; w < MAX_WIN; w++) 857 if (!(s->state & SOCKET_WIN_REQ(w))) break; 858 if (w == MAX_WIN) 859 return CS_OUT_OF_RESOURCE; 860 861 win = &s->win[w]; 862 win->magic = WINDOW_MAGIC; 863 win->index = w; 864 win->handle = *p_dev; 865 win->sock = s; 866 867 if (!(s->features & SS_CAP_STATIC_MAP)) { 868 win->ctl.res = pcmcia_find_mem_region(req->Base, req->Size, align, 869 (req->Attributes & WIN_MAP_BELOW_1MB), s); 870 if (!win->ctl.res) 871 return CS_IN_USE; 872 } 873 (*p_dev)->_win |= CLIENT_WIN_REQ(w); 874 875 /* Configure the socket controller */ 876 win->ctl.map = w+1; 877 win->ctl.flags = 0; 878 win->ctl.speed = req->AccessSpeed; 879 if (req->Attributes & WIN_MEMORY_TYPE) 880 win->ctl.flags |= MAP_ATTRIB; 881 if (req->Attributes & WIN_ENABLE) 882 win->ctl.flags |= MAP_ACTIVE; 883 if (req->Attributes & WIN_DATA_WIDTH_16) 884 win->ctl.flags |= MAP_16BIT; 885 if (req->Attributes & WIN_USE_WAIT) 886 win->ctl.flags |= MAP_USE_WAIT; 887 win->ctl.card_start = 0; 888 if (s->ops->set_mem_map(s, &win->ctl) != 0) 889 return CS_BAD_ARGS; 890 s->state |= SOCKET_WIN_REQ(w); 891 892 /* Return window handle */ 893 if (s->features & SS_CAP_STATIC_MAP) { 894 req->Base = win->ctl.static_start; 895 } else { 896 req->Base = win->ctl.res->start; 897 } 898 *wh = win; 899 900 return CS_SUCCESS; 901 } /* pcmcia_request_window */ 902 EXPORT_SYMBOL(pcmcia_request_window); 903 904 void pcmcia_disable_device(struct pcmcia_device *p_dev) { 905 pcmcia_release_configuration(p_dev); 906 pcmcia_release_io(p_dev, &p_dev->io); 907 pcmcia_release_irq(p_dev, &p_dev->irq); 908 if (p_dev->win) 909 pcmcia_release_window(p_dev->win); 910 } 911 EXPORT_SYMBOL(pcmcia_disable_device); 912