root/drivers/scsi/mac_esp.c

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

DEFINITIONS

This source file includes following definitions.
  1. mac_esp_write8
  2. mac_esp_read8
  3. mac_esp_reset_dma
  4. mac_esp_dma_drain
  5. mac_esp_dma_invalidate
  6. mac_esp_dma_error
  7. mac_esp_wait_for_empty_fifo
  8. mac_esp_wait_for_dreq
  9. mac_esp_send_pdma_cmd
  10. mac_esp_irq_pending
  11. mac_esp_dma_length_limit
  12. mac_scsi_esp_intr
  13. esp_mac_probe
  14. esp_mac_remove
  15. mac_esp_init
  16. mac_esp_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* mac_esp.c: ESP front-end for Macintosh Quadra systems.
   3  *
   4  * Adapted from jazz_esp.c and the old mac_esp.c.
   5  *
   6  * The pseudo DMA algorithm is based on the one used in NetBSD.
   7  * See sys/arch/mac68k/obio/esp.c for some background information.
   8  *
   9  * Copyright (C) 2007-2008 Finn Thain
  10  */
  11 
  12 #include <linux/kernel.h>
  13 #include <linux/types.h>
  14 #include <linux/module.h>
  15 #include <linux/init.h>
  16 #include <linux/interrupt.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/dma-mapping.h>
  19 #include <linux/scatterlist.h>
  20 #include <linux/delay.h>
  21 #include <linux/io.h>
  22 #include <linux/nubus.h>
  23 #include <linux/slab.h>
  24 
  25 #include <asm/irq.h>
  26 #include <asm/dma.h>
  27 #include <asm/macints.h>
  28 #include <asm/macintosh.h>
  29 #include <asm/mac_via.h>
  30 
  31 #include <scsi/scsi_host.h>
  32 
  33 #include "esp_scsi.h"
  34 
  35 #define DRV_MODULE_NAME     "mac_esp"
  36 #define PFX                 DRV_MODULE_NAME ": "
  37 #define DRV_VERSION         "1.000"
  38 #define DRV_MODULE_RELDATE  "Sept 15, 2007"
  39 
  40 #define MAC_ESP_IO_BASE          0x50F00000
  41 #define MAC_ESP_REGS_QUADRA      (MAC_ESP_IO_BASE + 0x10000)
  42 #define MAC_ESP_REGS_QUADRA2     (MAC_ESP_IO_BASE + 0xF000)
  43 #define MAC_ESP_REGS_QUADRA3     (MAC_ESP_IO_BASE + 0x18000)
  44 #define MAC_ESP_REGS_SPACING     0x402
  45 #define MAC_ESP_PDMA_REG         0xF9800024
  46 #define MAC_ESP_PDMA_REG_SPACING 0x4
  47 #define MAC_ESP_PDMA_IO_OFFSET   0x100
  48 
  49 #define esp_read8(REG)          mac_esp_read8(esp, REG)
  50 #define esp_write8(VAL, REG)    mac_esp_write8(esp, VAL, REG)
  51 
  52 struct mac_esp_priv {
  53         struct esp *esp;
  54         void __iomem *pdma_regs;
  55         void __iomem *pdma_io;
  56 };
  57 static struct esp *esp_chips[2];
  58 static DEFINE_SPINLOCK(esp_chips_lock);
  59 
  60 #define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \
  61                                dev_get_drvdata((esp)->dev))
  62 
  63 static inline void mac_esp_write8(struct esp *esp, u8 val, unsigned long reg)
  64 {
  65         nubus_writeb(val, esp->regs + reg * 16);
  66 }
  67 
  68 static inline u8 mac_esp_read8(struct esp *esp, unsigned long reg)
  69 {
  70         return nubus_readb(esp->regs + reg * 16);
  71 }
  72 
  73 static void mac_esp_reset_dma(struct esp *esp)
  74 {
  75         /* Nothing to do. */
  76 }
  77 
  78 static void mac_esp_dma_drain(struct esp *esp)
  79 {
  80         /* Nothing to do. */
  81 }
  82 
  83 static void mac_esp_dma_invalidate(struct esp *esp)
  84 {
  85         /* Nothing to do. */
  86 }
  87 
  88 static int mac_esp_dma_error(struct esp *esp)
  89 {
  90         return esp->send_cmd_error;
  91 }
  92 
  93 static inline int mac_esp_wait_for_empty_fifo(struct esp *esp)
  94 {
  95         int i = 500000;
  96 
  97         do {
  98                 if (!(esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES))
  99                         return 0;
 100 
 101                 if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
 102                         return 1;
 103 
 104                 udelay(2);
 105         } while (--i);
 106 
 107         printk(KERN_ERR PFX "FIFO is not empty (sreg %02x)\n",
 108                esp_read8(ESP_STATUS));
 109         esp->send_cmd_error = 1;
 110         return 1;
 111 }
 112 
 113 static inline int mac_esp_wait_for_dreq(struct esp *esp)
 114 {
 115         struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
 116         int i = 500000;
 117 
 118         do {
 119                 if (mep->pdma_regs == NULL) {
 120                         if (via2_scsi_drq_pending())
 121                                 return 0;
 122                 } else {
 123                         if (nubus_readl(mep->pdma_regs) & 0x200)
 124                                 return 0;
 125                 }
 126 
 127                 if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
 128                         return 1;
 129 
 130                 udelay(2);
 131         } while (--i);
 132 
 133         printk(KERN_ERR PFX "PDMA timeout (sreg %02x)\n",
 134                esp_read8(ESP_STATUS));
 135         esp->send_cmd_error = 1;
 136         return 1;
 137 }
 138 
 139 #define MAC_ESP_PDMA_LOOP(operands) \
 140         asm volatile ( \
 141              "       tstw %1                   \n" \
 142              "       jbeq 20f                  \n" \
 143              "1:     movew " operands "        \n" \
 144              "2:     movew " operands "        \n" \
 145              "3:     movew " operands "        \n" \
 146              "4:     movew " operands "        \n" \
 147              "5:     movew " operands "        \n" \
 148              "6:     movew " operands "        \n" \
 149              "7:     movew " operands "        \n" \
 150              "8:     movew " operands "        \n" \
 151              "9:     movew " operands "        \n" \
 152              "10:    movew " operands "        \n" \
 153              "11:    movew " operands "        \n" \
 154              "12:    movew " operands "        \n" \
 155              "13:    movew " operands "        \n" \
 156              "14:    movew " operands "        \n" \
 157              "15:    movew " operands "        \n" \
 158              "16:    movew " operands "        \n" \
 159              "       subqw #1,%1               \n" \
 160              "       jbne 1b                   \n" \
 161              "20:    tstw %2                   \n" \
 162              "       jbeq 30f                  \n" \
 163              "21:    movew " operands "        \n" \
 164              "       subqw #1,%2               \n" \
 165              "       jbne 21b                  \n" \
 166              "30:    tstw %3                   \n" \
 167              "       jbeq 40f                  \n" \
 168              "31:    moveb " operands "        \n" \
 169              "32:    nop                       \n" \
 170              "40:                              \n" \
 171              "                                 \n" \
 172              "       .section __ex_table,\"a\" \n" \
 173              "       .align  4                 \n" \
 174              "       .long   1b,40b            \n" \
 175              "       .long   2b,40b            \n" \
 176              "       .long   3b,40b            \n" \
 177              "       .long   4b,40b            \n" \
 178              "       .long   5b,40b            \n" \
 179              "       .long   6b,40b            \n" \
 180              "       .long   7b,40b            \n" \
 181              "       .long   8b,40b            \n" \
 182              "       .long   9b,40b            \n" \
 183              "       .long  10b,40b            \n" \
 184              "       .long  11b,40b            \n" \
 185              "       .long  12b,40b            \n" \
 186              "       .long  13b,40b            \n" \
 187              "       .long  14b,40b            \n" \
 188              "       .long  15b,40b            \n" \
 189              "       .long  16b,40b            \n" \
 190              "       .long  21b,40b            \n" \
 191              "       .long  31b,40b            \n" \
 192              "       .long  32b,40b            \n" \
 193              "       .previous                 \n" \
 194              : "+a" (addr), "+r" (count32), "+r" (count2) \
 195              : "g" (count1), "a" (mep->pdma_io))
 196 
 197 static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
 198                                   u32 dma_count, int write, u8 cmd)
 199 {
 200         struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
 201 
 202         esp->send_cmd_error = 0;
 203 
 204         if (!write)
 205                 scsi_esp_cmd(esp, ESP_CMD_FLUSH);
 206 
 207         esp_write8((esp_count >> 0) & 0xFF, ESP_TCLOW);
 208         esp_write8((esp_count >> 8) & 0xFF, ESP_TCMED);
 209 
 210         scsi_esp_cmd(esp, cmd);
 211 
 212         do {
 213                 unsigned int count32 = esp_count >> 5;
 214                 unsigned int count2 = (esp_count & 0x1F) >> 1;
 215                 unsigned int count1 = esp_count & 1;
 216                 unsigned int start_addr = addr;
 217 
 218                 if (mac_esp_wait_for_dreq(esp))
 219                         break;
 220 
 221                 if (write) {
 222                         MAC_ESP_PDMA_LOOP("%4@,%0@+");
 223 
 224                         esp_count -= addr - start_addr;
 225                 } else {
 226                         unsigned int n;
 227 
 228                         MAC_ESP_PDMA_LOOP("%0@+,%4@");
 229 
 230                         if (mac_esp_wait_for_empty_fifo(esp))
 231                                 break;
 232 
 233                         n = (esp_read8(ESP_TCMED) << 8) + esp_read8(ESP_TCLOW);
 234                         addr = start_addr + esp_count - n;
 235                         esp_count = n;
 236                 }
 237         } while (esp_count);
 238 }
 239 
 240 static int mac_esp_irq_pending(struct esp *esp)
 241 {
 242         if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
 243                 return 1;
 244         return 0;
 245 }
 246 
 247 static u32 mac_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len)
 248 {
 249         return dma_len > 0xFFFF ? 0xFFFF : dma_len;
 250 }
 251 
 252 static irqreturn_t mac_scsi_esp_intr(int irq, void *dev_id)
 253 {
 254         int got_intr;
 255 
 256         /*
 257          * This is an edge triggered IRQ, so we have to be careful to
 258          * avoid missing a transition when it is shared by two ESP devices.
 259          */
 260 
 261         do {
 262                 got_intr = 0;
 263                 if (esp_chips[0] &&
 264                     (mac_esp_read8(esp_chips[0], ESP_STATUS) & ESP_STAT_INTR)) {
 265                         (void)scsi_esp_intr(irq, esp_chips[0]);
 266                         got_intr = 1;
 267                 }
 268                 if (esp_chips[1] &&
 269                     (mac_esp_read8(esp_chips[1], ESP_STATUS) & ESP_STAT_INTR)) {
 270                         (void)scsi_esp_intr(irq, esp_chips[1]);
 271                         got_intr = 1;
 272                 }
 273         } while (got_intr);
 274 
 275         return IRQ_HANDLED;
 276 }
 277 
 278 static struct esp_driver_ops mac_esp_ops = {
 279         .esp_write8       = mac_esp_write8,
 280         .esp_read8        = mac_esp_read8,
 281         .irq_pending      = mac_esp_irq_pending,
 282         .dma_length_limit = mac_esp_dma_length_limit,
 283         .reset_dma        = mac_esp_reset_dma,
 284         .dma_drain        = mac_esp_dma_drain,
 285         .dma_invalidate   = mac_esp_dma_invalidate,
 286         .send_dma_cmd     = mac_esp_send_pdma_cmd,
 287         .dma_error        = mac_esp_dma_error,
 288 };
 289 
 290 static int esp_mac_probe(struct platform_device *dev)
 291 {
 292         struct scsi_host_template *tpnt = &scsi_esp_template;
 293         struct Scsi_Host *host;
 294         struct esp *esp;
 295         int err;
 296         struct mac_esp_priv *mep;
 297 
 298         if (!MACH_IS_MAC)
 299                 return -ENODEV;
 300 
 301         if (dev->id > 1)
 302                 return -ENODEV;
 303 
 304         host = scsi_host_alloc(tpnt, sizeof(struct esp));
 305 
 306         err = -ENOMEM;
 307         if (!host)
 308                 goto fail;
 309 
 310         host->max_id = 8;
 311         host->dma_boundary = PAGE_SIZE - 1;
 312         esp = shost_priv(host);
 313 
 314         esp->host = host;
 315         esp->dev = &dev->dev;
 316 
 317         esp->command_block = kzalloc(16, GFP_KERNEL);
 318         if (!esp->command_block)
 319                 goto fail_unlink;
 320         esp->command_block_dma = (dma_addr_t)esp->command_block;
 321 
 322         esp->scsi_id = 7;
 323         host->this_id = esp->scsi_id;
 324         esp->scsi_id_mask = 1 << esp->scsi_id;
 325 
 326         mep = kzalloc(sizeof(struct mac_esp_priv), GFP_KERNEL);
 327         if (!mep)
 328                 goto fail_free_command_block;
 329         mep->esp = esp;
 330         platform_set_drvdata(dev, mep);
 331 
 332         switch (macintosh_config->scsi_type) {
 333         case MAC_SCSI_QUADRA:
 334                 esp->cfreq     = 16500000;
 335                 esp->regs      = (void __iomem *)MAC_ESP_REGS_QUADRA;
 336                 mep->pdma_io   = esp->regs + MAC_ESP_PDMA_IO_OFFSET;
 337                 mep->pdma_regs = NULL;
 338                 break;
 339         case MAC_SCSI_QUADRA2:
 340                 esp->cfreq     = 25000000;
 341                 esp->regs      = (void __iomem *)(MAC_ESP_REGS_QUADRA2 +
 342                                  dev->id * MAC_ESP_REGS_SPACING);
 343                 mep->pdma_io   = esp->regs + MAC_ESP_PDMA_IO_OFFSET;
 344                 mep->pdma_regs = (void __iomem *)(MAC_ESP_PDMA_REG +
 345                                  dev->id * MAC_ESP_PDMA_REG_SPACING);
 346                 nubus_writel(0x1d1, mep->pdma_regs);
 347                 break;
 348         case MAC_SCSI_QUADRA3:
 349                 /* These quadras have a real DMA controller (the PSC) but we
 350                  * don't know how to drive it so we must use PIO instead.
 351                  */
 352                 esp->cfreq     = 25000000;
 353                 esp->regs      = (void __iomem *)MAC_ESP_REGS_QUADRA3;
 354                 mep->pdma_io   = NULL;
 355                 mep->pdma_regs = NULL;
 356                 break;
 357         }
 358         esp->fifo_reg = esp->regs + ESP_FDATA * 16;
 359 
 360         esp->ops = &mac_esp_ops;
 361         esp->flags = ESP_FLAG_NO_DMA_MAP;
 362         if (mep->pdma_io == NULL) {
 363                 printk(KERN_INFO PFX "using PIO for controller %d\n", dev->id);
 364                 esp_write8(0, ESP_TCLOW);
 365                 esp_write8(0, ESP_TCMED);
 366                 esp->flags |= ESP_FLAG_DISABLE_SYNC;
 367                 mac_esp_ops.send_dma_cmd = esp_send_pio_cmd;
 368         } else {
 369                 printk(KERN_INFO PFX "using PDMA for controller %d\n", dev->id);
 370         }
 371 
 372         host->irq = IRQ_MAC_SCSI;
 373 
 374         /* The request_irq() call is intended to succeed for the first device
 375          * and fail for the second device.
 376          */
 377         err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL);
 378         spin_lock(&esp_chips_lock);
 379         if (err < 0 && esp_chips[!dev->id] == NULL) {
 380                 spin_unlock(&esp_chips_lock);
 381                 goto fail_free_priv;
 382         }
 383         esp_chips[dev->id] = esp;
 384         spin_unlock(&esp_chips_lock);
 385 
 386         err = scsi_esp_register(esp);
 387         if (err)
 388                 goto fail_free_irq;
 389 
 390         return 0;
 391 
 392 fail_free_irq:
 393         spin_lock(&esp_chips_lock);
 394         esp_chips[dev->id] = NULL;
 395         if (esp_chips[!dev->id] == NULL) {
 396                 spin_unlock(&esp_chips_lock);
 397                 free_irq(host->irq, NULL);
 398         } else
 399                 spin_unlock(&esp_chips_lock);
 400 fail_free_priv:
 401         kfree(mep);
 402 fail_free_command_block:
 403         kfree(esp->command_block);
 404 fail_unlink:
 405         scsi_host_put(host);
 406 fail:
 407         return err;
 408 }
 409 
 410 static int esp_mac_remove(struct platform_device *dev)
 411 {
 412         struct mac_esp_priv *mep = platform_get_drvdata(dev);
 413         struct esp *esp = mep->esp;
 414         unsigned int irq = esp->host->irq;
 415 
 416         scsi_esp_unregister(esp);
 417 
 418         spin_lock(&esp_chips_lock);
 419         esp_chips[dev->id] = NULL;
 420         if (esp_chips[!dev->id] == NULL) {
 421                 spin_unlock(&esp_chips_lock);
 422                 free_irq(irq, NULL);
 423         } else
 424                 spin_unlock(&esp_chips_lock);
 425 
 426         kfree(mep);
 427 
 428         kfree(esp->command_block);
 429 
 430         scsi_host_put(esp->host);
 431 
 432         return 0;
 433 }
 434 
 435 static struct platform_driver esp_mac_driver = {
 436         .probe    = esp_mac_probe,
 437         .remove   = esp_mac_remove,
 438         .driver   = {
 439                 .name   = DRV_MODULE_NAME,
 440         },
 441 };
 442 
 443 static int __init mac_esp_init(void)
 444 {
 445         return platform_driver_register(&esp_mac_driver);
 446 }
 447 
 448 static void __exit mac_esp_exit(void)
 449 {
 450         platform_driver_unregister(&esp_mac_driver);
 451 }
 452 
 453 MODULE_DESCRIPTION("Mac ESP SCSI driver");
 454 MODULE_AUTHOR("Finn Thain");
 455 MODULE_LICENSE("GPL v2");
 456 MODULE_VERSION(DRV_VERSION);
 457 MODULE_ALIAS("platform:" DRV_MODULE_NAME);
 458 
 459 module_init(mac_esp_init);
 460 module_exit(mac_esp_exit);

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