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