root/drivers/scsi/mac53c94.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mac53c94_queue_lck
  2. DEF_SCSI_QCMD
  3. mac53c94_init
  4. mac53c94_start
  5. do_mac53c94_interrupt
  6. mac53c94_interrupt
  7. cmd_done
  8. set_dma_cmds
  9. mac53c94_probe
  10. mac53c94_remove
  11. init_mac53c94
  12. exit_mac53c94

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * SCSI low-level driver for the 53c94 SCSI bus adaptor found
   4  * on Power Macintosh computers, controlling the external SCSI chain.
   5  * We assume the 53c94 is connected to a DBDMA (descriptor-based DMA)
   6  * controller.
   7  *
   8  * Paul Mackerras, August 1996.
   9  * Copyright (C) 1996 Paul Mackerras.
  10  */
  11 #include <linux/kernel.h>
  12 #include <linux/delay.h>
  13 #include <linux/types.h>
  14 #include <linux/string.h>
  15 #include <linux/slab.h>
  16 #include <linux/blkdev.h>
  17 #include <linux/proc_fs.h>
  18 #include <linux/stat.h>
  19 #include <linux/spinlock.h>
  20 #include <linux/interrupt.h>
  21 #include <linux/module.h>
  22 #include <linux/pci.h>
  23 #include <asm/dbdma.h>
  24 #include <asm/io.h>
  25 #include <asm/pgtable.h>
  26 #include <asm/prom.h>
  27 #include <asm/macio.h>
  28 
  29 #include <scsi/scsi.h>
  30 #include <scsi/scsi_cmnd.h>
  31 #include <scsi/scsi_device.h>
  32 #include <scsi/scsi_host.h>
  33 
  34 #include "mac53c94.h"
  35 
  36 enum fsc_phase {
  37         idle,
  38         selecting,
  39         dataing,
  40         completing,
  41         busfreeing,
  42 };
  43 
  44 struct fsc_state {
  45         struct  mac53c94_regs __iomem *regs;
  46         int     intr;
  47         struct  dbdma_regs __iomem *dma;
  48         int     dmaintr;
  49         int     clk_freq;
  50         struct  Scsi_Host *host;
  51         struct scsi_cmnd *request_q;
  52         struct scsi_cmnd *request_qtail;
  53         struct scsi_cmnd *current_req;          /* req we're currently working on */
  54         enum fsc_phase phase;           /* what we're currently trying to do */
  55         struct dbdma_cmd *dma_cmds;     /* space for dbdma commands, aligned */
  56         void    *dma_cmd_space;
  57         struct  pci_dev *pdev;
  58         dma_addr_t dma_addr;
  59         struct macio_dev *mdev;
  60 };
  61 
  62 static void mac53c94_init(struct fsc_state *);
  63 static void mac53c94_start(struct fsc_state *);
  64 static void mac53c94_interrupt(int, void *);
  65 static irqreturn_t do_mac53c94_interrupt(int, void *);
  66 static void cmd_done(struct fsc_state *, int result);
  67 static void set_dma_cmds(struct fsc_state *, struct scsi_cmnd *);
  68 
  69 
  70 static int mac53c94_queue_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
  71 {
  72         struct fsc_state *state;
  73 
  74 #if 0
  75         if (cmd->sc_data_direction == DMA_TO_DEVICE) {
  76                 int i;
  77                 printk(KERN_DEBUG "mac53c94_queue %p: command is", cmd);
  78                 for (i = 0; i < cmd->cmd_len; ++i)
  79                         printk(KERN_CONT " %.2x", cmd->cmnd[i]);
  80                 printk(KERN_CONT "\n");
  81                 printk(KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n",
  82                        scsi_sg_count(cmd), scsi_bufflen(cmd), scsi_sglist(cmd));
  83         }
  84 #endif
  85 
  86         cmd->scsi_done = done;
  87         cmd->host_scribble = NULL;
  88 
  89         state = (struct fsc_state *) cmd->device->host->hostdata;
  90 
  91         if (state->request_q == NULL)
  92                 state->request_q = cmd;
  93         else
  94                 state->request_qtail->host_scribble = (void *) cmd;
  95         state->request_qtail = cmd;
  96 
  97         if (state->phase == idle)
  98                 mac53c94_start(state);
  99 
 100         return 0;
 101 }
 102 
 103 static DEF_SCSI_QCMD(mac53c94_queue)
 104 
 105 static int mac53c94_host_reset(struct scsi_cmnd *cmd)
 106 {
 107         struct fsc_state *state = (struct fsc_state *) cmd->device->host->hostdata;
 108         struct mac53c94_regs __iomem *regs = state->regs;
 109         struct dbdma_regs __iomem *dma = state->dma;
 110         unsigned long flags;
 111 
 112         spin_lock_irqsave(cmd->device->host->host_lock, flags);
 113 
 114         writel((RUN|PAUSE|FLUSH|WAKE) << 16, &dma->control);
 115         writeb(CMD_SCSI_RESET, &regs->command); /* assert RST */
 116         udelay(100);                    /* leave it on for a while (>= 25us) */
 117         writeb(CMD_RESET, &regs->command);
 118         udelay(20);
 119         mac53c94_init(state);
 120         writeb(CMD_NOP, &regs->command);
 121 
 122         spin_unlock_irqrestore(cmd->device->host->host_lock, flags);
 123         return SUCCESS;
 124 }
 125 
 126 static void mac53c94_init(struct fsc_state *state)
 127 {
 128         struct mac53c94_regs __iomem *regs = state->regs;
 129         struct dbdma_regs __iomem *dma = state->dma;
 130         int x;
 131 
 132         writeb(state->host->this_id | CF1_PAR_ENABLE, &regs->config1);
 133         writeb(TIMO_VAL(250), &regs->sel_timeout);      /* 250ms */
 134         writeb(CLKF_VAL(state->clk_freq), &regs->clk_factor);
 135         writeb(CF2_FEATURE_EN, &regs->config2);
 136         writeb(0, &regs->config3);
 137         writeb(0, &regs->sync_period);
 138         writeb(0, &regs->sync_offset);
 139         x = readb(&regs->interrupt);
 140         writel((RUN|PAUSE|FLUSH|WAKE) << 16, &dma->control);
 141 }
 142 
 143 /*
 144  * Start the next command for a 53C94.
 145  * Should be called with interrupts disabled.
 146  */
 147 static void mac53c94_start(struct fsc_state *state)
 148 {
 149         struct scsi_cmnd *cmd;
 150         struct mac53c94_regs __iomem *regs = state->regs;
 151         int i;
 152 
 153         if (state->phase != idle || state->current_req != NULL)
 154                 panic("inappropriate mac53c94_start (state=%p)", state);
 155         if (state->request_q == NULL)
 156                 return;
 157         state->current_req = cmd = state->request_q;
 158         state->request_q = (struct scsi_cmnd *) cmd->host_scribble;
 159 
 160         /* Off we go */
 161         writeb(0, &regs->count_lo);
 162         writeb(0, &regs->count_mid);
 163         writeb(0, &regs->count_hi);
 164         writeb(CMD_NOP + CMD_DMA_MODE, &regs->command);
 165         udelay(1);
 166         writeb(CMD_FLUSH, &regs->command);
 167         udelay(1);
 168         writeb(cmd->device->id, &regs->dest_id);
 169         writeb(0, &regs->sync_period);
 170         writeb(0, &regs->sync_offset);
 171 
 172         /* load the command into the FIFO */
 173         for (i = 0; i < cmd->cmd_len; ++i)
 174                 writeb(cmd->cmnd[i], &regs->fifo);
 175 
 176         /* do select without ATN XXX */
 177         writeb(CMD_SELECT, &regs->command);
 178         state->phase = selecting;
 179 
 180         set_dma_cmds(state, cmd);
 181 }
 182 
 183 static irqreturn_t do_mac53c94_interrupt(int irq, void *dev_id)
 184 {
 185         unsigned long flags;
 186         struct Scsi_Host *dev = ((struct fsc_state *) dev_id)->current_req->device->host;
 187         
 188         spin_lock_irqsave(dev->host_lock, flags);
 189         mac53c94_interrupt(irq, dev_id);
 190         spin_unlock_irqrestore(dev->host_lock, flags);
 191         return IRQ_HANDLED;
 192 }
 193 
 194 static void mac53c94_interrupt(int irq, void *dev_id)
 195 {
 196         struct fsc_state *state = (struct fsc_state *) dev_id;
 197         struct mac53c94_regs __iomem *regs = state->regs;
 198         struct dbdma_regs __iomem *dma = state->dma;
 199         struct scsi_cmnd *cmd = state->current_req;
 200         int nb, stat, seq, intr;
 201         static int mac53c94_errors;
 202 
 203         /*
 204          * Apparently, reading the interrupt register unlatches
 205          * the status and sequence step registers.
 206          */
 207         seq = readb(&regs->seqstep);
 208         stat = readb(&regs->status);
 209         intr = readb(&regs->interrupt);
 210 
 211 #if 0
 212         printk(KERN_DEBUG "mac53c94_intr, intr=%x stat=%x seq=%x phase=%d\n",
 213                intr, stat, seq, state->phase);
 214 #endif
 215 
 216         if (intr & INTR_RESET) {
 217                 /* SCSI bus was reset */
 218                 printk(KERN_INFO "external SCSI bus reset detected\n");
 219                 writeb(CMD_NOP, &regs->command);
 220                 writel(RUN << 16, &dma->control);       /* stop dma */
 221                 cmd_done(state, DID_RESET << 16);
 222                 return;
 223         }
 224         if (intr & INTR_ILL_CMD) {
 225                 printk(KERN_ERR "53c94: invalid cmd, intr=%x stat=%x seq=%x phase=%d\n",
 226                        intr, stat, seq, state->phase);
 227                 cmd_done(state, DID_ERROR << 16);
 228                 return;
 229         }
 230         if (stat & STAT_ERROR) {
 231 #if 0
 232                 /* XXX these seem to be harmless? */
 233                 printk("53c94: bad error, intr=%x stat=%x seq=%x phase=%d\n",
 234                        intr, stat, seq, state->phase);
 235 #endif
 236                 ++mac53c94_errors;
 237                 writeb(CMD_NOP + CMD_DMA_MODE, &regs->command);
 238         }
 239         if (cmd == 0) {
 240                 printk(KERN_DEBUG "53c94: interrupt with no command active?\n");
 241                 return;
 242         }
 243         if (stat & STAT_PARITY) {
 244                 printk(KERN_ERR "mac53c94: parity error\n");
 245                 cmd_done(state, DID_PARITY << 16);
 246                 return;
 247         }
 248         switch (state->phase) {
 249         case selecting:
 250                 if (intr & INTR_DISCONNECT) {
 251                         /* selection timed out */
 252                         cmd_done(state, DID_BAD_TARGET << 16);
 253                         return;
 254                 }
 255                 if (intr != INTR_BUS_SERV + INTR_DONE) {
 256                         printk(KERN_DEBUG "got intr %x during selection\n", intr);
 257                         cmd_done(state, DID_ERROR << 16);
 258                         return;
 259                 }
 260                 if ((seq & SS_MASK) != SS_DONE) {
 261                         printk(KERN_DEBUG "seq step %x after command\n", seq);
 262                         cmd_done(state, DID_ERROR << 16);
 263                         return;
 264                 }
 265                 writeb(CMD_NOP, &regs->command);
 266                 /* set DMA controller going if any data to transfer */
 267                 if ((stat & (STAT_MSG|STAT_CD)) == 0
 268                     && (scsi_sg_count(cmd) > 0 || scsi_bufflen(cmd))) {
 269                         nb = cmd->SCp.this_residual;
 270                         if (nb > 0xfff0)
 271                                 nb = 0xfff0;
 272                         cmd->SCp.this_residual -= nb;
 273                         writeb(nb, &regs->count_lo);
 274                         writeb(nb >> 8, &regs->count_mid);
 275                         writeb(CMD_DMA_MODE + CMD_NOP, &regs->command);
 276                         writel(virt_to_phys(state->dma_cmds), &dma->cmdptr);
 277                         writel((RUN << 16) | RUN, &dma->control);
 278                         writeb(CMD_DMA_MODE + CMD_XFER_DATA, &regs->command);
 279                         state->phase = dataing;
 280                         break;
 281                 } else if ((stat & STAT_PHASE) == STAT_CD + STAT_IO) {
 282                         /* up to status phase already */
 283                         writeb(CMD_I_COMPLETE, &regs->command);
 284                         state->phase = completing;
 285                 } else {
 286                         printk(KERN_DEBUG "in unexpected phase %x after cmd\n",
 287                                stat & STAT_PHASE);
 288                         cmd_done(state, DID_ERROR << 16);
 289                         return;
 290                 }
 291                 break;
 292 
 293         case dataing:
 294                 if (intr != INTR_BUS_SERV) {
 295                         printk(KERN_DEBUG "got intr %x before status\n", intr);
 296                         cmd_done(state, DID_ERROR << 16);
 297                         return;
 298                 }
 299                 if (cmd->SCp.this_residual != 0
 300                     && (stat & (STAT_MSG|STAT_CD)) == 0) {
 301                         /* Set up the count regs to transfer more */
 302                         nb = cmd->SCp.this_residual;
 303                         if (nb > 0xfff0)
 304                                 nb = 0xfff0;
 305                         cmd->SCp.this_residual -= nb;
 306                         writeb(nb, &regs->count_lo);
 307                         writeb(nb >> 8, &regs->count_mid);
 308                         writeb(CMD_DMA_MODE + CMD_NOP, &regs->command);
 309                         writeb(CMD_DMA_MODE + CMD_XFER_DATA, &regs->command);
 310                         break;
 311                 }
 312                 if ((stat & STAT_PHASE) != STAT_CD + STAT_IO) {
 313                         printk(KERN_DEBUG "intr %x before data xfer complete\n", intr);
 314                 }
 315                 writel(RUN << 16, &dma->control);       /* stop dma */
 316                 scsi_dma_unmap(cmd);
 317                 /* should check dma status */
 318                 writeb(CMD_I_COMPLETE, &regs->command);
 319                 state->phase = completing;
 320                 break;
 321         case completing:
 322                 if (intr != INTR_DONE) {
 323                         printk(KERN_DEBUG "got intr %x on completion\n", intr);
 324                         cmd_done(state, DID_ERROR << 16);
 325                         return;
 326                 }
 327                 cmd->SCp.Status = readb(&regs->fifo);
 328                 cmd->SCp.Message = readb(&regs->fifo);
 329                 cmd->result = CMD_ACCEPT_MSG;
 330                 writeb(CMD_ACCEPT_MSG, &regs->command);
 331                 state->phase = busfreeing;
 332                 break;
 333         case busfreeing:
 334                 if (intr != INTR_DISCONNECT) {
 335                         printk(KERN_DEBUG "got intr %x when expected disconnect\n", intr);
 336                 }
 337                 cmd_done(state, (DID_OK << 16) + (cmd->SCp.Message << 8)
 338                          + cmd->SCp.Status);
 339                 break;
 340         default:
 341                 printk(KERN_DEBUG "don't know about phase %d\n", state->phase);
 342         }
 343 }
 344 
 345 static void cmd_done(struct fsc_state *state, int result)
 346 {
 347         struct scsi_cmnd *cmd;
 348 
 349         cmd = state->current_req;
 350         if (cmd != 0) {
 351                 cmd->result = result;
 352                 (*cmd->scsi_done)(cmd);
 353                 state->current_req = NULL;
 354         }
 355         state->phase = idle;
 356         mac53c94_start(state);
 357 }
 358 
 359 /*
 360  * Set up DMA commands for transferring data.
 361  */
 362 static void set_dma_cmds(struct fsc_state *state, struct scsi_cmnd *cmd)
 363 {
 364         int i, dma_cmd, total, nseg;
 365         struct scatterlist *scl;
 366         struct dbdma_cmd *dcmds;
 367         dma_addr_t dma_addr;
 368         u32 dma_len;
 369 
 370         nseg = scsi_dma_map(cmd);
 371         BUG_ON(nseg < 0);
 372         if (!nseg)
 373                 return;
 374 
 375         dma_cmd = cmd->sc_data_direction == DMA_TO_DEVICE ?
 376                         OUTPUT_MORE : INPUT_MORE;
 377         dcmds = state->dma_cmds;
 378         total = 0;
 379 
 380         scsi_for_each_sg(cmd, scl, nseg, i) {
 381                 dma_addr = sg_dma_address(scl);
 382                 dma_len = sg_dma_len(scl);
 383                 if (dma_len > 0xffff)
 384                         panic("mac53c94: scatterlist element >= 64k");
 385                 total += dma_len;
 386                 dcmds->req_count = cpu_to_le16(dma_len);
 387                 dcmds->command = cpu_to_le16(dma_cmd);
 388                 dcmds->phy_addr = cpu_to_le32(dma_addr);
 389                 dcmds->xfer_status = 0;
 390                 ++dcmds;
 391         }
 392 
 393         dma_cmd += OUTPUT_LAST - OUTPUT_MORE;
 394         dcmds[-1].command = cpu_to_le16(dma_cmd);
 395         dcmds->command = cpu_to_le16(DBDMA_STOP);
 396         cmd->SCp.this_residual = total;
 397 }
 398 
 399 static struct scsi_host_template mac53c94_template = {
 400         .proc_name      = "53c94",
 401         .name           = "53C94",
 402         .queuecommand   = mac53c94_queue,
 403         .eh_host_reset_handler = mac53c94_host_reset,
 404         .can_queue      = 1,
 405         .this_id        = 7,
 406         .sg_tablesize   = SG_ALL,
 407         .max_segment_size = 65535,
 408 };
 409 
 410 static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *match)
 411 {
 412         struct device_node *node = macio_get_of_node(mdev);
 413         struct pci_dev *pdev = macio_get_pci_dev(mdev);
 414         struct fsc_state *state;
 415         struct Scsi_Host *host;
 416         void *dma_cmd_space;
 417         const unsigned char *clkprop;
 418         int proplen, rc = -ENODEV;
 419 
 420         if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) {
 421                 printk(KERN_ERR "mac53c94: expected 2 addrs and intrs"
 422                        " (got %d/%d)\n",
 423                        macio_resource_count(mdev), macio_irq_count(mdev));
 424                 return -ENODEV;
 425         }
 426 
 427         if (macio_request_resources(mdev, "mac53c94") != 0) {
 428                 printk(KERN_ERR "mac53c94: unable to request memory resources");
 429                 return -EBUSY;
 430         }
 431 
 432         host = scsi_host_alloc(&mac53c94_template, sizeof(struct fsc_state));
 433         if (host == NULL) {
 434                 printk(KERN_ERR "mac53c94: couldn't register host");
 435                 rc = -ENOMEM;
 436                 goto out_release;
 437         }
 438 
 439         state = (struct fsc_state *) host->hostdata;
 440         macio_set_drvdata(mdev, state);
 441         state->host = host;
 442         state->pdev = pdev;
 443         state->mdev = mdev;
 444 
 445         state->regs = (struct mac53c94_regs __iomem *)
 446                 ioremap(macio_resource_start(mdev, 0), 0x1000);
 447         state->intr = macio_irq(mdev, 0);
 448         state->dma = (struct dbdma_regs __iomem *)
 449                 ioremap(macio_resource_start(mdev, 1), 0x1000);
 450         state->dmaintr = macio_irq(mdev, 1);
 451         if (state->regs == NULL || state->dma == NULL) {
 452                 printk(KERN_ERR "mac53c94: ioremap failed for %pOF\n", node);
 453                 goto out_free;
 454         }
 455 
 456         clkprop = of_get_property(node, "clock-frequency", &proplen);
 457         if (clkprop == NULL || proplen != sizeof(int)) {
 458                 printk(KERN_ERR "%pOF: can't get clock frequency, "
 459                        "assuming 25MHz\n", node);
 460                 state->clk_freq = 25000000;
 461         } else
 462                 state->clk_freq = *(int *)clkprop;
 463 
 464         /* Space for dma command list: +1 for stop command,
 465          * +1 to allow for aligning.
 466          * XXX FIXME: Use DMA consistent routines
 467          */
 468         dma_cmd_space = kmalloc_array(host->sg_tablesize + 2,
 469                                              sizeof(struct dbdma_cmd),
 470                                              GFP_KERNEL);
 471         if (dma_cmd_space == 0) {
 472                 printk(KERN_ERR "mac53c94: couldn't allocate dma "
 473                        "command space for %pOF\n", node);
 474                 rc = -ENOMEM;
 475                 goto out_free;
 476         }
 477         state->dma_cmds = (struct dbdma_cmd *)DBDMA_ALIGN(dma_cmd_space);
 478         memset(state->dma_cmds, 0, (host->sg_tablesize + 1)
 479                * sizeof(struct dbdma_cmd));
 480         state->dma_cmd_space = dma_cmd_space;
 481 
 482         mac53c94_init(state);
 483 
 484         if (request_irq(state->intr, do_mac53c94_interrupt, 0, "53C94",state)) {
 485                 printk(KERN_ERR "mac53C94: can't get irq %d for %pOF\n",
 486                        state->intr, node);
 487                 goto out_free_dma;
 488         }
 489 
 490         rc = scsi_add_host(host, &mdev->ofdev.dev);
 491         if (rc != 0)
 492                 goto out_release_irq;
 493 
 494         scsi_scan_host(host);
 495         return 0;
 496 
 497  out_release_irq:
 498         free_irq(state->intr, state);
 499  out_free_dma:
 500         kfree(state->dma_cmd_space);
 501  out_free:
 502         if (state->dma != NULL)
 503                 iounmap(state->dma);
 504         if (state->regs != NULL)
 505                 iounmap(state->regs);
 506         scsi_host_put(host);
 507  out_release:
 508         macio_release_resources(mdev);
 509 
 510         return rc;
 511 }
 512 
 513 static int mac53c94_remove(struct macio_dev *mdev)
 514 {
 515         struct fsc_state *fp = (struct fsc_state *)macio_get_drvdata(mdev);
 516         struct Scsi_Host *host = fp->host;
 517 
 518         scsi_remove_host(host);
 519 
 520         free_irq(fp->intr, fp);
 521 
 522         if (fp->regs)
 523                 iounmap(fp->regs);
 524         if (fp->dma)
 525                 iounmap(fp->dma);
 526         kfree(fp->dma_cmd_space);
 527 
 528         scsi_host_put(host);
 529 
 530         macio_release_resources(mdev);
 531 
 532         return 0;
 533 }
 534 
 535 
 536 static struct of_device_id mac53c94_match[] = 
 537 {
 538         {
 539         .name           = "53c94",
 540         },
 541         {},
 542 };
 543 MODULE_DEVICE_TABLE (of, mac53c94_match);
 544 
 545 static struct macio_driver mac53c94_driver = 
 546 {
 547         .driver = {
 548                 .name           = "mac53c94",
 549                 .owner          = THIS_MODULE,
 550                 .of_match_table = mac53c94_match,
 551         },
 552         .probe          = mac53c94_probe,
 553         .remove         = mac53c94_remove,
 554 };
 555 
 556 
 557 static int __init init_mac53c94(void)
 558 {
 559         return macio_register_driver(&mac53c94_driver);
 560 }
 561 
 562 static void __exit exit_mac53c94(void)
 563 {
 564         return macio_unregister_driver(&mac53c94_driver);
 565 }
 566 
 567 module_init(init_mac53c94);
 568 module_exit(exit_mac53c94);
 569 
 570 MODULE_DESCRIPTION("PowerMac 53c94 SCSI driver");
 571 MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
 572 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */