1 /* 2 * Sun3 SCSI stuff by Erik Verbruggen (erik@bigmama.xtdnet.nl) 3 * 4 * Sun3 DMA routines added by Sam Creasey (sammy@sammy.net) 5 * 6 * VME support added by Sam Creasey 7 * 8 * TODO: modify this driver to support multiple Sun3 SCSI VME boards 9 * 10 * Adapted from mac_scsinew.c: 11 */ 12 /* 13 * Generic Macintosh NCR5380 driver 14 * 15 * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov> 16 * 17 * derived in part from: 18 */ 19 /* 20 * Generic Generic NCR5380 driver 21 * 22 * Copyright 1995, Russell King 23 */ 24 25 #include <linux/types.h> 26 #include <linux/delay.h> 27 #include <linux/module.h> 28 #include <linux/ioport.h> 29 #include <linux/init.h> 30 #include <linux/blkdev.h> 31 #include <linux/platform_device.h> 32 33 #include <asm/io.h> 34 #include <asm/dvma.h> 35 36 #include <scsi/scsi_host.h> 37 38 /* minimum number of bytes to do dma on */ 39 #define DMA_MIN_SIZE 129 40 41 /* Definitions for the core NCR5380 driver. */ 42 43 #define NCR5380_implementation_fields /* none */ 44 45 #define NCR5380_read(reg) in_8(hostdata->io + (reg)) 46 #define NCR5380_write(reg, value) out_8(hostdata->io + (reg), value) 47 48 #define NCR5380_queue_command sun3scsi_queue_command 49 #define NCR5380_host_reset sun3scsi_host_reset 50 #define NCR5380_abort sun3scsi_abort 51 #define NCR5380_info sun3scsi_info 52 53 #define NCR5380_dma_xfer_len sun3scsi_dma_xfer_len 54 #define NCR5380_dma_recv_setup sun3scsi_dma_count 55 #define NCR5380_dma_send_setup sun3scsi_dma_count 56 #define NCR5380_dma_residual sun3scsi_dma_residual 57 58 #include "NCR5380.h" 59 60 /* dma regs start at regbase + 8, directly after the NCR regs */ 61 struct sun3_dma_regs { 62 unsigned short dma_addr_hi; /* vme only */ 63 unsigned short dma_addr_lo; /* vme only */ 64 unsigned short dma_count_hi; /* vme only */ 65 unsigned short dma_count_lo; /* vme only */ 66 unsigned short udc_data; /* udc dma data reg (obio only) */ 67 unsigned short udc_addr; /* uda dma addr reg (obio only) */ 68 unsigned short fifo_data; /* fifo data reg, 69 * holds extra byte on odd dma reads 70 */ 71 unsigned short fifo_count; 72 unsigned short csr; /* control/status reg */ 73 unsigned short bpack_hi; /* vme only */ 74 unsigned short bpack_lo; /* vme only */ 75 unsigned short ivect; /* vme only */ 76 unsigned short fifo_count_hi; /* vme only */ 77 }; 78 79 /* ucd chip specific regs - live in dvma space */ 80 struct sun3_udc_regs { 81 unsigned short rsel; /* select regs to load */ 82 unsigned short addr_hi; /* high word of addr */ 83 unsigned short addr_lo; /* low word */ 84 unsigned short count; /* words to be xfer'd */ 85 unsigned short mode_hi; /* high word of channel mode */ 86 unsigned short mode_lo; /* low word of channel mode */ 87 }; 88 89 /* addresses of the udc registers */ 90 #define UDC_MODE 0x38 91 #define UDC_CSR 0x2e /* command/status */ 92 #define UDC_CHN_HI 0x26 /* chain high word */ 93 #define UDC_CHN_LO 0x22 /* chain lo word */ 94 #define UDC_CURA_HI 0x1a /* cur reg A high */ 95 #define UDC_CURA_LO 0x0a /* cur reg A low */ 96 #define UDC_CURB_HI 0x12 /* cur reg B high */ 97 #define UDC_CURB_LO 0x02 /* cur reg B low */ 98 #define UDC_MODE_HI 0x56 /* mode reg high */ 99 #define UDC_MODE_LO 0x52 /* mode reg low */ 100 #define UDC_COUNT 0x32 /* words to xfer */ 101 102 /* some udc commands */ 103 #define UDC_RESET 0 104 #define UDC_CHN_START 0xa0 /* start chain */ 105 #define UDC_INT_ENABLE 0x32 /* channel 1 int on */ 106 107 /* udc mode words */ 108 #define UDC_MODE_HIWORD 0x40 109 #define UDC_MODE_LSEND 0xc2 110 #define UDC_MODE_LRECV 0xd2 111 112 /* udc reg selections */ 113 #define UDC_RSEL_SEND 0x282 114 #define UDC_RSEL_RECV 0x182 115 116 /* bits in csr reg */ 117 #define CSR_DMA_ACTIVE 0x8000 118 #define CSR_DMA_CONFLICT 0x4000 119 #define CSR_DMA_BUSERR 0x2000 120 121 #define CSR_FIFO_EMPTY 0x400 /* fifo flushed? */ 122 #define CSR_SDB_INT 0x200 /* sbc interrupt pending */ 123 #define CSR_DMA_INT 0x100 /* dma interrupt pending */ 124 125 #define CSR_LEFT 0xc0 126 #define CSR_LEFT_3 0xc0 127 #define CSR_LEFT_2 0x80 128 #define CSR_LEFT_1 0x40 129 #define CSR_PACK_ENABLE 0x20 130 131 #define CSR_DMA_ENABLE 0x10 132 133 #define CSR_SEND 0x8 /* 1 = send 0 = recv */ 134 #define CSR_FIFO 0x2 /* reset fifo */ 135 #define CSR_INTR 0x4 /* interrupt enable */ 136 #define CSR_SCSI 0x1 137 138 #define VME_DATA24 0x3d00 139 140 extern int sun3_map_test(unsigned long, char *); 141 142 static int setup_can_queue = -1; 143 module_param(setup_can_queue, int, 0); 144 static int setup_cmd_per_lun = -1; 145 module_param(setup_cmd_per_lun, int, 0); 146 static int setup_sg_tablesize = -1; 147 module_param(setup_sg_tablesize, int, 0); 148 static int setup_hostid = -1; 149 module_param(setup_hostid, int, 0); 150 151 /* ms to wait after hitting dma regs */ 152 #define SUN3_DMA_DELAY 10 153 154 /* dvma buffer to allocate -- 32k should hopefully be more than sufficient */ 155 #define SUN3_DVMA_BUFSIZE 0xe000 156 157 static struct scsi_cmnd *sun3_dma_setup_done; 158 static volatile struct sun3_dma_regs *dregs; 159 static struct sun3_udc_regs *udc_regs; 160 static unsigned char *sun3_dma_orig_addr; 161 static unsigned long sun3_dma_orig_count; 162 static int sun3_dma_active; 163 static unsigned long last_residual; 164 165 #ifndef SUN3_SCSI_VME 166 /* dma controller register access functions */ 167 168 static inline unsigned short sun3_udc_read(unsigned char reg) 169 { 170 unsigned short ret; 171 172 dregs->udc_addr = UDC_CSR; 173 udelay(SUN3_DMA_DELAY); 174 ret = dregs->udc_data; 175 udelay(SUN3_DMA_DELAY); 176 177 return ret; 178 } 179 180 static inline void sun3_udc_write(unsigned short val, unsigned char reg) 181 { 182 dregs->udc_addr = reg; 183 udelay(SUN3_DMA_DELAY); 184 dregs->udc_data = val; 185 udelay(SUN3_DMA_DELAY); 186 } 187 #endif 188 189 // safe bits for the CSR 190 #define CSR_GOOD 0x060f 191 192 static irqreturn_t scsi_sun3_intr(int irq, void *dev) 193 { 194 struct Scsi_Host *instance = dev; 195 unsigned short csr = dregs->csr; 196 int handled = 0; 197 198 #ifdef SUN3_SCSI_VME 199 dregs->csr &= ~CSR_DMA_ENABLE; 200 #endif 201 202 if(csr & ~CSR_GOOD) { 203 if (csr & CSR_DMA_BUSERR) 204 shost_printk(KERN_ERR, instance, "bus error in DMA\n"); 205 if (csr & CSR_DMA_CONFLICT) 206 shost_printk(KERN_ERR, instance, "DMA conflict\n"); 207 handled = 1; 208 } 209 210 if(csr & (CSR_SDB_INT | CSR_DMA_INT)) { 211 NCR5380_intr(irq, dev); 212 handled = 1; 213 } 214 215 return IRQ_RETVAL(handled); 216 } 217 218 /* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */ 219 static int sun3scsi_dma_setup(struct NCR5380_hostdata *hostdata, 220 unsigned char *data, int count, int write_flag) 221 { 222 void *addr; 223 224 if(sun3_dma_orig_addr != NULL) 225 dvma_unmap(sun3_dma_orig_addr); 226 227 #ifdef SUN3_SCSI_VME 228 addr = (void *)dvma_map_vme((unsigned long) data, count); 229 #else 230 addr = (void *)dvma_map((unsigned long) data, count); 231 #endif 232 233 sun3_dma_orig_addr = addr; 234 sun3_dma_orig_count = count; 235 236 #ifndef SUN3_SCSI_VME 237 dregs->fifo_count = 0; 238 sun3_udc_write(UDC_RESET, UDC_CSR); 239 240 /* reset fifo */ 241 dregs->csr &= ~CSR_FIFO; 242 dregs->csr |= CSR_FIFO; 243 #endif 244 245 /* set direction */ 246 if(write_flag) 247 dregs->csr |= CSR_SEND; 248 else 249 dregs->csr &= ~CSR_SEND; 250 251 #ifdef SUN3_SCSI_VME 252 dregs->csr |= CSR_PACK_ENABLE; 253 254 dregs->dma_addr_hi = ((unsigned long)addr >> 16); 255 dregs->dma_addr_lo = ((unsigned long)addr & 0xffff); 256 257 dregs->dma_count_hi = 0; 258 dregs->dma_count_lo = 0; 259 dregs->fifo_count_hi = 0; 260 dregs->fifo_count = 0; 261 #else 262 /* byte count for fifo */ 263 dregs->fifo_count = count; 264 265 sun3_udc_write(UDC_RESET, UDC_CSR); 266 267 /* reset fifo */ 268 dregs->csr &= ~CSR_FIFO; 269 dregs->csr |= CSR_FIFO; 270 271 if(dregs->fifo_count != count) { 272 shost_printk(KERN_ERR, hostdata->host, 273 "FIFO mismatch %04x not %04x\n", 274 dregs->fifo_count, (unsigned int) count); 275 NCR5380_dprint(NDEBUG_DMA, hostdata->host); 276 } 277 278 /* setup udc */ 279 udc_regs->addr_hi = (((unsigned long)(addr) & 0xff0000) >> 8); 280 udc_regs->addr_lo = ((unsigned long)(addr) & 0xffff); 281 udc_regs->count = count/2; /* count in words */ 282 udc_regs->mode_hi = UDC_MODE_HIWORD; 283 if(write_flag) { 284 if(count & 1) 285 udc_regs->count++; 286 udc_regs->mode_lo = UDC_MODE_LSEND; 287 udc_regs->rsel = UDC_RSEL_SEND; 288 } else { 289 udc_regs->mode_lo = UDC_MODE_LRECV; 290 udc_regs->rsel = UDC_RSEL_RECV; 291 } 292 293 /* announce location of regs block */ 294 sun3_udc_write(((dvma_vtob(udc_regs) & 0xff0000) >> 8), 295 UDC_CHN_HI); 296 297 sun3_udc_write((dvma_vtob(udc_regs) & 0xffff), UDC_CHN_LO); 298 299 /* set dma master on */ 300 sun3_udc_write(0xd, UDC_MODE); 301 302 /* interrupt enable */ 303 sun3_udc_write(UDC_INT_ENABLE, UDC_CSR); 304 #endif 305 306 return count; 307 308 } 309 310 static int sun3scsi_dma_count(struct NCR5380_hostdata *hostdata, 311 unsigned char *data, int count) 312 { 313 return count; 314 } 315 316 static inline int sun3scsi_dma_recv_setup(struct NCR5380_hostdata *hostdata, 317 unsigned char *data, int count) 318 { 319 return sun3scsi_dma_setup(hostdata, data, count, 0); 320 } 321 322 static inline int sun3scsi_dma_send_setup(struct NCR5380_hostdata *hostdata, 323 unsigned char *data, int count) 324 { 325 return sun3scsi_dma_setup(hostdata, data, count, 1); 326 } 327 328 static int sun3scsi_dma_residual(struct NCR5380_hostdata *hostdata) 329 { 330 return last_residual; 331 } 332 333 static int sun3scsi_dma_xfer_len(struct NCR5380_hostdata *hostdata, 334 struct scsi_cmnd *cmd) 335 { 336 int wanted_len = cmd->SCp.this_residual; 337 338 if (wanted_len < DMA_MIN_SIZE || blk_rq_is_passthrough(cmd->request)) 339 return 0; 340 341 return wanted_len; 342 } 343 344 static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data) 345 { 346 #ifdef SUN3_SCSI_VME 347 unsigned short csr; 348 349 csr = dregs->csr; 350 351 dregs->dma_count_hi = (sun3_dma_orig_count >> 16); 352 dregs->dma_count_lo = (sun3_dma_orig_count & 0xffff); 353 354 dregs->fifo_count_hi = (sun3_dma_orig_count >> 16); 355 dregs->fifo_count = (sun3_dma_orig_count & 0xffff); 356 357 /* if(!(csr & CSR_DMA_ENABLE)) 358 * dregs->csr |= CSR_DMA_ENABLE; 359 */ 360 #else 361 sun3_udc_write(UDC_CHN_START, UDC_CSR); 362 #endif 363 364 return 0; 365 } 366 367 /* clean up after our dma is done */ 368 static int sun3scsi_dma_finish(int write_flag) 369 { 370 unsigned short __maybe_unused count; 371 unsigned short fifo; 372 int ret = 0; 373 374 sun3_dma_active = 0; 375 376 #ifdef SUN3_SCSI_VME 377 dregs->csr &= ~CSR_DMA_ENABLE; 378 379 fifo = dregs->fifo_count; 380 if (write_flag) { 381 if ((fifo > 0) && (fifo < sun3_dma_orig_count)) 382 fifo++; 383 } 384 385 last_residual = fifo; 386 /* empty bytes from the fifo which didn't make it */ 387 if ((!write_flag) && (dregs->csr & CSR_LEFT)) { 388 unsigned char *vaddr; 389 390 vaddr = (unsigned char *)dvma_vmetov(sun3_dma_orig_addr); 391 392 vaddr += (sun3_dma_orig_count - fifo); 393 vaddr--; 394 395 switch (dregs->csr & CSR_LEFT) { 396 case CSR_LEFT_3: 397 *vaddr = (dregs->bpack_lo & 0xff00) >> 8; 398 vaddr--; 399 400 case CSR_LEFT_2: 401 *vaddr = (dregs->bpack_hi & 0x00ff); 402 vaddr--; 403 404 case CSR_LEFT_1: 405 *vaddr = (dregs->bpack_hi & 0xff00) >> 8; 406 break; 407 } 408 } 409 #else 410 // check to empty the fifo on a read 411 if(!write_flag) { 412 int tmo = 20000; /* .2 sec */ 413 414 while(1) { 415 if(dregs->csr & CSR_FIFO_EMPTY) 416 break; 417 418 if(--tmo <= 0) { 419 printk("sun3scsi: fifo failed to empty!\n"); 420 return 1; 421 } 422 udelay(10); 423 } 424 } 425 426 dregs->udc_addr = 0x32; 427 udelay(SUN3_DMA_DELAY); 428 count = 2 * dregs->udc_data; 429 udelay(SUN3_DMA_DELAY); 430 431 fifo = dregs->fifo_count; 432 last_residual = fifo; 433 434 /* empty bytes from the fifo which didn't make it */ 435 if((!write_flag) && (count - fifo) == 2) { 436 unsigned short data; 437 unsigned char *vaddr; 438 439 data = dregs->fifo_data; 440 vaddr = (unsigned char *)dvma_btov(sun3_dma_orig_addr); 441 442 vaddr += (sun3_dma_orig_count - fifo); 443 444 vaddr[-2] = (data & 0xff00) >> 8; 445 vaddr[-1] = (data & 0xff); 446 } 447 #endif 448 449 dvma_unmap(sun3_dma_orig_addr); 450 sun3_dma_orig_addr = NULL; 451 452 #ifdef SUN3_SCSI_VME 453 dregs->dma_addr_hi = 0; 454 dregs->dma_addr_lo = 0; 455 dregs->dma_count_hi = 0; 456 dregs->dma_count_lo = 0; 457 458 dregs->fifo_count = 0; 459 dregs->fifo_count_hi = 0; 460 461 dregs->csr &= ~CSR_SEND; 462 /* dregs->csr |= CSR_DMA_ENABLE; */ 463 #else 464 sun3_udc_write(UDC_RESET, UDC_CSR); 465 dregs->fifo_count = 0; 466 dregs->csr &= ~CSR_SEND; 467 468 /* reset fifo */ 469 dregs->csr &= ~CSR_FIFO; 470 dregs->csr |= CSR_FIFO; 471 #endif 472 473 sun3_dma_setup_done = NULL; 474 475 return ret; 476 477 } 478 479 #include "NCR5380.c" 480 481 #ifdef SUN3_SCSI_VME 482 #define SUN3_SCSI_NAME "Sun3 NCR5380 VME SCSI" 483 #define DRV_MODULE_NAME "sun3_scsi_vme" 484 #else 485 #define SUN3_SCSI_NAME "Sun3 NCR5380 SCSI" 486 #define DRV_MODULE_NAME "sun3_scsi" 487 #endif 488 489 #define PFX DRV_MODULE_NAME ": " 490 491 static struct scsi_host_template sun3_scsi_template = { 492 .module = THIS_MODULE, 493 .proc_name = DRV_MODULE_NAME, 494 .name = SUN3_SCSI_NAME, 495 .info = sun3scsi_info, 496 .queuecommand = sun3scsi_queue_command, 497 .eh_abort_handler = sun3scsi_abort, 498 .eh_host_reset_handler = sun3scsi_host_reset, 499 .can_queue = 16, 500 .this_id = 7, 501 .sg_tablesize = SG_NONE, 502 .cmd_per_lun = 2, 503 .dma_boundary = PAGE_SIZE - 1, 504 .cmd_size = NCR5380_CMD_SIZE, 505 }; 506 507 static int __init sun3_scsi_probe(struct platform_device *pdev) 508 { 509 struct Scsi_Host *instance; 510 struct NCR5380_hostdata *hostdata; 511 int error; 512 struct resource *irq, *mem; 513 void __iomem *ioaddr; 514 int host_flags = 0; 515 #ifdef SUN3_SCSI_VME 516 int i; 517 #endif 518 519 if (setup_can_queue > 0) 520 sun3_scsi_template.can_queue = setup_can_queue; 521 if (setup_cmd_per_lun > 0) 522 sun3_scsi_template.cmd_per_lun = setup_cmd_per_lun; 523 if (setup_sg_tablesize >= 0) 524 sun3_scsi_template.sg_tablesize = setup_sg_tablesize; 525 if (setup_hostid >= 0) 526 sun3_scsi_template.this_id = setup_hostid & 7; 527 528 #ifdef SUN3_SCSI_VME 529 ioaddr = NULL; 530 for (i = 0; i < 2; i++) { 531 unsigned char x; 532 533 irq = platform_get_resource(pdev, IORESOURCE_IRQ, i); 534 mem = platform_get_resource(pdev, IORESOURCE_MEM, i); 535 if (!irq || !mem) 536 break; 537 538 ioaddr = sun3_ioremap(mem->start, resource_size(mem), 539 SUN3_PAGE_TYPE_VME16); 540 dregs = (struct sun3_dma_regs *)(ioaddr + 8); 541 542 if (sun3_map_test((unsigned long)dregs, &x)) { 543 unsigned short oldcsr; 544 545 oldcsr = dregs->csr; 546 dregs->csr = 0; 547 udelay(SUN3_DMA_DELAY); 548 if (dregs->csr == 0x1400) 549 break; 550 551 dregs->csr = oldcsr; 552 } 553 554 iounmap(ioaddr); 555 ioaddr = NULL; 556 } 557 if (!ioaddr) 558 return -ENODEV; 559 #else 560 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 561 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 562 if (!irq || !mem) 563 return -ENODEV; 564 565 ioaddr = ioremap(mem->start, resource_size(mem)); 566 dregs = (struct sun3_dma_regs *)(ioaddr + 8); 567 568 udc_regs = dvma_malloc(sizeof(struct sun3_udc_regs)); 569 if (!udc_regs) { 570 pr_err(PFX "couldn't allocate DVMA memory!\n"); 571 iounmap(ioaddr); 572 return -ENOMEM; 573 } 574 #endif 575 576 instance = scsi_host_alloc(&sun3_scsi_template, 577 sizeof(struct NCR5380_hostdata)); 578 if (!instance) { 579 error = -ENOMEM; 580 goto fail_alloc; 581 } 582 583 instance->irq = irq->start; 584 585 hostdata = shost_priv(instance); 586 hostdata->base = mem->start; 587 hostdata->io = ioaddr; 588 589 error = NCR5380_init(instance, host_flags); 590 if (error) 591 goto fail_init; 592 593 error = request_irq(instance->irq, scsi_sun3_intr, 0, 594 "NCR5380", instance); 595 if (error) { 596 pr_err(PFX "scsi%d: IRQ %d not free, bailing out\n", 597 instance->host_no, instance->irq); 598 goto fail_irq; 599 } 600 601 dregs->csr = 0; 602 udelay(SUN3_DMA_DELAY); 603 dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR; 604 udelay(SUN3_DMA_DELAY); 605 dregs->fifo_count = 0; 606 #ifdef SUN3_SCSI_VME 607 dregs->fifo_count_hi = 0; 608 dregs->dma_addr_hi = 0; 609 dregs->dma_addr_lo = 0; 610 dregs->dma_count_hi = 0; 611 dregs->dma_count_lo = 0; 612 613 dregs->ivect = VME_DATA24 | (instance->irq & 0xff); 614 #endif 615 616 NCR5380_maybe_reset_bus(instance); 617 618 error = scsi_add_host(instance, NULL); 619 if (error) 620 goto fail_host; 621 622 platform_set_drvdata(pdev, instance); 623 624 scsi_scan_host(instance); 625 return 0; 626 627 fail_host: 628 free_irq(instance->irq, instance); 629 fail_irq: 630 NCR5380_exit(instance); 631 fail_init: 632 scsi_host_put(instance); 633 fail_alloc: 634 if (udc_regs) 635 dvma_free(udc_regs); 636 iounmap(ioaddr); 637 return error; 638 } 639 640 static int __exit sun3_scsi_remove(struct platform_device *pdev) 641 { 642 struct Scsi_Host *instance = platform_get_drvdata(pdev); 643 struct NCR5380_hostdata *hostdata = shost_priv(instance); 644 void __iomem *ioaddr = hostdata->io; 645 646 scsi_remove_host(instance); 647 free_irq(instance->irq, instance); 648 NCR5380_exit(instance); 649 scsi_host_put(instance); 650 if (udc_regs) 651 dvma_free(udc_regs); 652 iounmap(ioaddr); 653 return 0; 654 } 655 656 static struct platform_driver sun3_scsi_driver = { 657 .remove = __exit_p(sun3_scsi_remove), 658 .driver = { 659 .name = DRV_MODULE_NAME, 660 }, 661 }; 662 663 module_platform_driver_probe(sun3_scsi_driver, sun3_scsi_probe); 664 665 MODULE_ALIAS("platform:" DRV_MODULE_NAME); 666 MODULE_LICENSE("GPL"); 667