Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | /* * include/asm-sparc/dma.h * * Don't even ask, I am figuring out how this crap works * on the Sparc. It may end up being real hairy to plug * into this code, maybe not, we'll see. * * Copyright 1995 (C) David S. Miller (davem@caip.rutgers.edu) */ #ifndef _ASM_SPARC_DMA_H #define _ASM_SPARC_DMA_H #include <asm/vac-ops.h> /* for invalidate's, etc. */ #include <asm/sbus.h> #include <asm/delay.h> #include <asm/oplib.h> /* DMA probing routine */ extern unsigned long probe_dma(unsigned long); /* These are irrelevant for Sparc DMA, but we leave it in so that * things can compile. */ #define MAX_DMA_CHANNELS 8 #define MAX_DMA_ADDRESS 0x0 /* Structure to describe the current status of DMA registers on the Sparc */ struct sparc_dma_registers { volatile unsigned long cond_reg; /* DMA condition register */ volatile char * st_addr; /* Start address of this transfer */ volatile unsigned long cnt; /* How many bytes to transfer */ volatile unsigned long dma_test; /* DMA test register */ }; /* Linux DMA information structure, filled during probe. */ struct Linux_SBus_DMA { struct linux_sbus_device *SBus_dev; /* pointer to sbus device struct */ struct sparc_dma_registers *DMA_regs; /* Pointer to DMA regs in IO space */ /* Status, misc info */ int node; /* Prom node for this DMA device */ int dma_running; /* Are we using the DMA now? */ /* DMA revision: 0=REV0 1=REV1 2=REV2 3=DMA_PLUS */ int dma_rev; }; extern struct Linux_SBus_DMA Sparc_DMA; /* Main routines in dma.c */ extern void dump_dma_regs(struct sparc_dma_registers *); extern unsigned long probe_dma(unsigned long); extern void sparc_dma_init_transfer(struct sparc_dma_registers *, unsigned long, int, int); extern int sparc_dma_interrupt(struct sparc_dma_registers *); /* Fields in the cond_reg register */ /* First, the version identification bits */ #define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */ #define DMA_VERS0 0x00000000 /* Sunray DMA version */ #define DMA_VERS1 0x80000000 /* DMA rev 1 */ #define DMA_VERS2 0xa0000000 /* DMA rev 2 */ #define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */ #define DMA_HNDL_INTR 0x00000001 /* An interrupt needs to be handled */ #define DMA_HNDL_ERROR 0x00000002 /* We need to take care of an error */ #define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */ #define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */ #define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */ #define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */ #define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */ #define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */ #define DMA_ST_WRITE 0x00000100 /* If set, write from device to memory */ #define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */ #define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Read is pending */ #define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */ #define DMA_TERM_CNTR 0x00004000 /* Terminal counter */ #define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */ #define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */ #define DMA_BRST_SZ 0x000c0000 /* SBUS transfer r/w burst size */ #define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */ #define DMA_2CLKS 0x00200000 /* Each transfer equals 2 clock ticks */ #define DMA_3CLKS 0x00400000 /* Each transfer equals 3 clock ticks */ #define DMA_CNTR_DISAB 0x00800000 /* No intr's when DMA_TERM_CNTR is set */ #define DMA_AUTO_NADDR 0x01000000 /* Use "auto next address" feature */ #define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */ #define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */ #define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */ /* Only 24-bits of the byte count are significant */ #define DMA_BYTE_CNT_MASK 0x00ffffff /* Pause until counter runs out or BIT isn't set in the DMA condition * register. */ extern inline void sparc_dma_pause(struct sparc_dma_registers *dma_regs, unsigned long bit) { int ctr = 50000; /* Let's find some bugs ;) */ /* Busy wait until the bit is not set any more */ while((dma_regs->cond_reg&bit) && (ctr>0)) { ctr--; __delay(1); } /* Check for bogus outcome. */ if(ctr==0) { printk("DMA Grrr: I tried for wait for the assertion of bit %08xl to clear", (unsigned int) bit); printk(" in the DMA condition register and it did not!\n"); printk("Cannot continue, halting...\n"); prom_halt(); } return; } /* Enable DMA interrupts */ extern inline void sparc_dma_enable_interrupts(struct sparc_dma_registers *dma_regs) { dma_regs->cond_reg |= DMA_INT_ENAB; } /* Disable DMA interrupts from coming in */ extern inline void sparc_dma_disable_interrupts(struct sparc_dma_registers *dma_regs) { dma_regs->cond_reg &= ~(DMA_INT_ENAB); } /* Reset the DMA module. */ extern inline void sparc_dma_reset(struct sparc_dma_registers *dma_regs) { /* Let the current FIFO drain itself */ sparc_dma_pause(dma_regs, (DMA_FIFO_ISDRAIN)); /* Reset the logic */ dma_regs->cond_reg |= (DMA_RST_SCSI); /* assert */ __delay(400); /* let the bits set ;) */ dma_regs->cond_reg &= ~(DMA_RST_SCSI); /* de-assert */ sparc_dma_enable_interrupts(dma_regs); /* Re-enable interrupts */ /* Enable FAST transfers if available */ if(Sparc_DMA.dma_rev>1) { dma_regs->cond_reg |= DMA_3CLKS; } Sparc_DMA.dma_running = 0; return; } #endif /* !(_ASM_SPARC_DMA_H) */ |