Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ncr5380: Add support for HP C2502

HP C2502 cards (based on 53C400A chips) use different magic numbers for
software-based I/O address configuration than other cards.
The configuration is also extended to allow setting the IRQ.

Move the configuration to a new function magic_configure() and move
magic the magic numbers into an array. Add new magic numbers for these
HP cards and hp_c2502 module parameter to use them, e.g.:
modprobe g_NCR5380 ncr_irq=7 ncr_addr=0x280 hp_c2502=1

Tested with HP C2502 and DTCT-436P.

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Ondrej Zary and committed by
Martin K. Petersen
c6084cbc 42fc6370

+59 -16
+58 -16
drivers/scsi/g_NCR5380.c
··· 80 80 static int ncr_53c400; 81 81 static int ncr_53c400a; 82 82 static int dtc_3181e; 83 + static int hp_c2502; 83 84 84 85 static struct override { 85 86 NCR5380_map_type NCR5380_map_name; ··· 226 225 227 226 #endif 228 227 228 + #ifndef SCSI_G_NCR5380_MEM 229 + /* 230 + * Configure I/O address of 53C400A or DTC436 by writing magic numbers 231 + * to ports 0x779 and 0x379. 232 + */ 233 + static void magic_configure(int idx, u8 irq, u8 magic[]) 234 + { 235 + u8 cfg = 0; 236 + 237 + outb(magic[0], 0x779); 238 + outb(magic[1], 0x379); 239 + outb(magic[2], 0x379); 240 + outb(magic[3], 0x379); 241 + outb(magic[4], 0x379); 242 + 243 + /* allowed IRQs for HP C2502 */ 244 + if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7) 245 + irq = 0; 246 + if (idx >= 0 && idx <= 7) 247 + cfg = 0x80 | idx | (irq << 4); 248 + outb(cfg, 0x379); 249 + } 250 + #endif 251 + 229 252 /** 230 253 * generic_NCR5380_detect - look for NCR5380 controllers 231 254 * @tpnt: the scsi template ··· 266 241 static int current_override; 267 242 int count; 268 243 unsigned int *ports; 244 + u8 *magic = NULL; 269 245 #ifndef SCSI_G_NCR5380_MEM 270 246 int i; 247 + int port_idx = -1; 271 248 unsigned long region_size = 16; 272 249 #endif 273 250 static unsigned int __initdata ncr_53c400a_ports[] = { ··· 277 250 }; 278 251 static unsigned int __initdata dtc_3181e_ports[] = { 279 252 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0 253 + }; 254 + static u8 ncr_53c400a_magic[] __initdata = { /* 53C400A & DTC436 */ 255 + 0x59, 0xb9, 0xc5, 0xae, 0xa6 256 + }; 257 + static u8 hp_c2502_magic[] __initdata = { /* HP C2502 */ 258 + 0x0f, 0x22, 0xf0, 0x20, 0x80 280 259 }; 281 260 int flags; 282 261 struct Scsi_Host *instance; ··· 306 273 overrides[0].board = BOARD_NCR53C400A; 307 274 else if (dtc_3181e) 308 275 overrides[0].board = BOARD_DTC3181E; 276 + else if (hp_c2502) 277 + overrides[0].board = BOARD_HP_C2502; 309 278 #ifndef SCSI_G_NCR5380_MEM 310 279 if (!current_override && isapnp_present()) { 311 280 struct pnp_dev *dev = NULL; ··· 360 325 case BOARD_NCR53C400A: 361 326 flags = FLAG_NO_DMA_FIXUP; 362 327 ports = ncr_53c400a_ports; 328 + magic = ncr_53c400a_magic; 329 + break; 330 + case BOARD_HP_C2502: 331 + flags = FLAG_NO_DMA_FIXUP; 332 + ports = ncr_53c400a_ports; 333 + magic = hp_c2502_magic; 363 334 break; 364 335 case BOARD_DTC3181E: 365 336 flags = FLAG_NO_DMA_FIXUP; 366 337 ports = dtc_3181e_ports; 338 + magic = ncr_53c400a_magic; 367 339 break; 368 340 } 369 341 370 342 #ifndef SCSI_G_NCR5380_MEM 371 - if (ports) { 343 + if (ports && magic) { 372 344 /* wakeup sequence for the NCR53C400A and DTC3181E */ 373 345 374 346 /* Disable the adapter and look for a free io port */ 375 - outb(0x59, 0x779); 376 - outb(0xb9, 0x379); 377 - outb(0xc5, 0x379); 378 - outb(0xae, 0x379); 379 - outb(0xa6, 0x379); 380 - outb(0x00, 0x379); 347 + magic_configure(-1, 0, magic); 381 348 382 349 if (overrides[current_override].NCR5380_map_name != PORT_AUTO) 383 350 for (i = 0; ports[i]; i++) { ··· 398 361 } 399 362 if (ports[i]) { 400 363 /* At this point we have our region reserved */ 401 - outb(0x59, 0x779); 402 - outb(0xb9, 0x379); 403 - outb(0xc5, 0x379); 404 - outb(0xae, 0x379); 405 - outb(0xa6, 0x379); 406 - outb(0x80 | i, 0x379); /* set io port to be used */ 364 + magic_configure(i, 0, magic); /* no IRQ yet */ 407 365 outb(0xc0, ports[i] + 9); 408 366 if (inb(ports[i] + 9) != 0x80) 409 367 continue; 410 - else 411 - overrides[current_override].NCR5380_map_name = ports[i]; 368 + overrides[current_override].NCR5380_map_name = ports[i]; 369 + port_idx = i; 412 370 } else 413 371 continue; 414 372 } ··· 449 417 hostdata->io_width = 2; /* 16-bit PDMA */ 450 418 /* fall through */ 451 419 case BOARD_NCR53C400A: 420 + case BOARD_HP_C2502: 452 421 hostdata->c400_ctl_status = 9; 453 422 hostdata->c400_blk_cnt = 10; 454 423 hostdata->c400_host_buf = 8; ··· 466 433 break; 467 434 case BOARD_DTC3181E: 468 435 case BOARD_NCR53C400A: 436 + case BOARD_HP_C2502: 469 437 pr_err(DRV_MODULE_NAME ": unknown register offsets\n"); 470 438 goto out_unregister; 471 439 } ··· 479 445 case BOARD_NCR53C400: 480 446 case BOARD_DTC3181E: 481 447 case BOARD_NCR53C400A: 448 + case BOARD_HP_C2502: 482 449 NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); 483 450 } 484 451 ··· 494 459 if (instance->irq == 255) 495 460 instance->irq = NO_IRQ; 496 461 497 - if (instance->irq != NO_IRQ) 462 + if (instance->irq != NO_IRQ) { 463 + #ifndef SCSI_G_NCR5380_MEM 464 + /* set IRQ for HP C2502 */ 465 + if (overrides[current_override].board == BOARD_HP_C2502) 466 + magic_configure(port_idx, instance->irq, magic); 467 + #endif 498 468 if (request_irq(instance->irq, generic_NCR5380_intr, 499 469 0, "NCR5380", instance)) { 500 470 printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); 501 471 instance->irq = NO_IRQ; 502 472 } 473 + } 503 474 504 475 if (instance->irq == NO_IRQ) { 505 476 printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); ··· 792 751 module_param(ncr_53c400, int, 0); 793 752 module_param(ncr_53c400a, int, 0); 794 753 module_param(dtc_3181e, int, 0); 754 + module_param(hp_c2502, int, 0); 795 755 MODULE_LICENSE("GPL"); 796 756 797 757 #if !defined(SCSI_G_NCR5380_MEM) && defined(MODULE)
+1
drivers/scsi/g_NCR5380.h
··· 88 88 #define BOARD_NCR53C400 1 89 89 #define BOARD_NCR53C400A 2 90 90 #define BOARD_DTC3181E 3 91 + #define BOARD_HP_C2502 4 91 92 92 93 #endif /* GENERIC_NCR5380_H */ 93 94