18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_DMA_H 38c2ecf20Sopenharmony_ci#define _ASM_POWERPC_DMA_H 48c2ecf20Sopenharmony_ci#ifdef __KERNEL__ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci/* 78c2ecf20Sopenharmony_ci * Defines for using and allocating dma channels. 88c2ecf20Sopenharmony_ci * Written by Hennus Bergman, 1992. 98c2ecf20Sopenharmony_ci * High DMA channel support & info by Hannu Savolainen 108c2ecf20Sopenharmony_ci * and John Boyd, Nov. 1992. 118c2ecf20Sopenharmony_ci * Changes for ppc sound by Christoph Nadig 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* 158c2ecf20Sopenharmony_ci * Note: Adapted for PowerPC by Gary Thomas 168c2ecf20Sopenharmony_ci * Modified by Cort Dougan <cort@cs.nmt.edu> 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * None of this really applies for Power Macintoshes. There is 198c2ecf20Sopenharmony_ci * basically just enough here to get kernel/dma.c to compile. 208c2ecf20Sopenharmony_ci */ 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include <asm/io.h> 238c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#ifndef MAX_DMA_CHANNELS 268c2ecf20Sopenharmony_ci#define MAX_DMA_CHANNELS 8 278c2ecf20Sopenharmony_ci#endif 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* The maximum address that we can perform a DMA transfer to on this platform */ 308c2ecf20Sopenharmony_ci/* Doesn't really apply... */ 318c2ecf20Sopenharmony_ci#define MAX_DMA_ADDRESS (~0UL) 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER 348c2ecf20Sopenharmony_ci#define dma_outb outb_p 358c2ecf20Sopenharmony_ci#else 368c2ecf20Sopenharmony_ci#define dma_outb outb 378c2ecf20Sopenharmony_ci#endif 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define dma_inb inb 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* 428c2ecf20Sopenharmony_ci * NOTES about DMA transfers: 438c2ecf20Sopenharmony_ci * 448c2ecf20Sopenharmony_ci * controller 1: channels 0-3, byte operations, ports 00-1F 458c2ecf20Sopenharmony_ci * controller 2: channels 4-7, word operations, ports C0-DF 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * - ALL registers are 8 bits only, regardless of transfer size 488c2ecf20Sopenharmony_ci * - channel 4 is not used - cascades 1 into 2. 498c2ecf20Sopenharmony_ci * - channels 0-3 are byte - addresses/counts are for physical bytes 508c2ecf20Sopenharmony_ci * - channels 5-7 are word - addresses/counts are for physical words 518c2ecf20Sopenharmony_ci * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries 528c2ecf20Sopenharmony_ci * - transfer count loaded to registers is 1 less than actual count 538c2ecf20Sopenharmony_ci * - controller 2 offsets are all even (2x offsets for controller 1) 548c2ecf20Sopenharmony_ci * - page registers for 5-7 don't use data bit 0, represent 128K pages 558c2ecf20Sopenharmony_ci * - page registers for 0-3 use bit 0, represent 64K pages 568c2ecf20Sopenharmony_ci * 578c2ecf20Sopenharmony_ci * On CHRP, the W83C553F (and VLSI Tollgate?) support full 32 bit addressing. 588c2ecf20Sopenharmony_ci * Note that addresses loaded into registers must be _physical_ addresses, 598c2ecf20Sopenharmony_ci * not logical addresses (which may differ if paging is active). 608c2ecf20Sopenharmony_ci * 618c2ecf20Sopenharmony_ci * Address mapping for channels 0-3: 628c2ecf20Sopenharmony_ci * 638c2ecf20Sopenharmony_ci * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses) 648c2ecf20Sopenharmony_ci * | ... | | ... | | ... | 658c2ecf20Sopenharmony_ci * | ... | | ... | | ... | 668c2ecf20Sopenharmony_ci * | ... | | ... | | ... | 678c2ecf20Sopenharmony_ci * P7 ... P0 A7 ... A0 A7 ... A0 688c2ecf20Sopenharmony_ci * | Page | Addr MSB | Addr LSB | (DMA registers) 698c2ecf20Sopenharmony_ci * 708c2ecf20Sopenharmony_ci * Address mapping for channels 5-7: 718c2ecf20Sopenharmony_ci * 728c2ecf20Sopenharmony_ci * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses) 738c2ecf20Sopenharmony_ci * | ... | \ \ ... \ \ \ ... \ \ 748c2ecf20Sopenharmony_ci * | ... | \ \ ... \ \ \ ... \ (not used) 758c2ecf20Sopenharmony_ci * | ... | \ \ ... \ \ \ ... \ 768c2ecf20Sopenharmony_ci * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0 778c2ecf20Sopenharmony_ci * | Page | Addr MSB | Addr LSB | (DMA registers) 788c2ecf20Sopenharmony_ci * 798c2ecf20Sopenharmony_ci * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses 808c2ecf20Sopenharmony_ci * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at 818c2ecf20Sopenharmony_ci * the hardware level, so odd-byte transfers aren't possible). 828c2ecf20Sopenharmony_ci * 838c2ecf20Sopenharmony_ci * Transfer count (_not # bytes_) is limited to 64K, represented as actual 848c2ecf20Sopenharmony_ci * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more, 858c2ecf20Sopenharmony_ci * and up to 128K bytes may be transferred on channels 5-7 in one operation. 868c2ecf20Sopenharmony_ci * 878c2ecf20Sopenharmony_ci */ 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci/* 8237 DMA controllers */ 908c2ecf20Sopenharmony_ci#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ 918c2ecf20Sopenharmony_ci#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci/* DMA controller registers */ 948c2ecf20Sopenharmony_ci#define DMA1_CMD_REG 0x08 /* command register (w) */ 958c2ecf20Sopenharmony_ci#define DMA1_STAT_REG 0x08 /* status register (r) */ 968c2ecf20Sopenharmony_ci#define DMA1_REQ_REG 0x09 /* request register (w) */ 978c2ecf20Sopenharmony_ci#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */ 988c2ecf20Sopenharmony_ci#define DMA1_MODE_REG 0x0B /* mode register (w) */ 998c2ecf20Sopenharmony_ci#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */ 1008c2ecf20Sopenharmony_ci#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */ 1018c2ecf20Sopenharmony_ci#define DMA1_RESET_REG 0x0D /* Master Clear (w) */ 1028c2ecf20Sopenharmony_ci#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ 1038c2ecf20Sopenharmony_ci#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci#define DMA2_CMD_REG 0xD0 /* command register (w) */ 1068c2ecf20Sopenharmony_ci#define DMA2_STAT_REG 0xD0 /* status register (r) */ 1078c2ecf20Sopenharmony_ci#define DMA2_REQ_REG 0xD2 /* request register (w) */ 1088c2ecf20Sopenharmony_ci#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */ 1098c2ecf20Sopenharmony_ci#define DMA2_MODE_REG 0xD6 /* mode register (w) */ 1108c2ecf20Sopenharmony_ci#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */ 1118c2ecf20Sopenharmony_ci#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */ 1128c2ecf20Sopenharmony_ci#define DMA2_RESET_REG 0xDA /* Master Clear (w) */ 1138c2ecf20Sopenharmony_ci#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ 1148c2ecf20Sopenharmony_ci#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci#define DMA_ADDR_0 0x00 /* DMA address registers */ 1178c2ecf20Sopenharmony_ci#define DMA_ADDR_1 0x02 1188c2ecf20Sopenharmony_ci#define DMA_ADDR_2 0x04 1198c2ecf20Sopenharmony_ci#define DMA_ADDR_3 0x06 1208c2ecf20Sopenharmony_ci#define DMA_ADDR_4 0xC0 1218c2ecf20Sopenharmony_ci#define DMA_ADDR_5 0xC4 1228c2ecf20Sopenharmony_ci#define DMA_ADDR_6 0xC8 1238c2ecf20Sopenharmony_ci#define DMA_ADDR_7 0xCC 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci#define DMA_CNT_0 0x01 /* DMA count registers */ 1268c2ecf20Sopenharmony_ci#define DMA_CNT_1 0x03 1278c2ecf20Sopenharmony_ci#define DMA_CNT_2 0x05 1288c2ecf20Sopenharmony_ci#define DMA_CNT_3 0x07 1298c2ecf20Sopenharmony_ci#define DMA_CNT_4 0xC2 1308c2ecf20Sopenharmony_ci#define DMA_CNT_5 0xC6 1318c2ecf20Sopenharmony_ci#define DMA_CNT_6 0xCA 1328c2ecf20Sopenharmony_ci#define DMA_CNT_7 0xCE 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci#define DMA_LO_PAGE_0 0x87 /* DMA page registers */ 1358c2ecf20Sopenharmony_ci#define DMA_LO_PAGE_1 0x83 1368c2ecf20Sopenharmony_ci#define DMA_LO_PAGE_2 0x81 1378c2ecf20Sopenharmony_ci#define DMA_LO_PAGE_3 0x82 1388c2ecf20Sopenharmony_ci#define DMA_LO_PAGE_5 0x8B 1398c2ecf20Sopenharmony_ci#define DMA_LO_PAGE_6 0x89 1408c2ecf20Sopenharmony_ci#define DMA_LO_PAGE_7 0x8A 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci#define DMA_HI_PAGE_0 0x487 /* DMA page registers */ 1438c2ecf20Sopenharmony_ci#define DMA_HI_PAGE_1 0x483 1448c2ecf20Sopenharmony_ci#define DMA_HI_PAGE_2 0x481 1458c2ecf20Sopenharmony_ci#define DMA_HI_PAGE_3 0x482 1468c2ecf20Sopenharmony_ci#define DMA_HI_PAGE_5 0x48B 1478c2ecf20Sopenharmony_ci#define DMA_HI_PAGE_6 0x489 1488c2ecf20Sopenharmony_ci#define DMA_HI_PAGE_7 0x48A 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci#define DMA1_EXT_REG 0x40B 1518c2ecf20Sopenharmony_ci#define DMA2_EXT_REG 0x4D6 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci#ifndef __powerpc64__ 1548c2ecf20Sopenharmony_ci /* in arch/powerpc/kernel/setup_32.c -- Cort */ 1558c2ecf20Sopenharmony_ci extern unsigned int DMA_MODE_WRITE; 1568c2ecf20Sopenharmony_ci extern unsigned int DMA_MODE_READ; 1578c2ecf20Sopenharmony_ci#else 1588c2ecf20Sopenharmony_ci #define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ 1598c2ecf20Sopenharmony_ci #define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ 1608c2ecf20Sopenharmony_ci#endif 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci#define DMA_AUTOINIT 0x10 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ciextern spinlock_t dma_spin_lock; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic __inline__ unsigned long claim_dma_lock(void) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci unsigned long flags; 1718c2ecf20Sopenharmony_ci spin_lock_irqsave(&dma_spin_lock, flags); 1728c2ecf20Sopenharmony_ci return flags; 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic __inline__ void release_dma_lock(unsigned long flags) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dma_spin_lock, flags); 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci/* enable/disable a specific DMA channel */ 1818c2ecf20Sopenharmony_cistatic __inline__ void enable_dma(unsigned int dmanr) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci unsigned char ucDmaCmd = 0x00; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci if (dmanr != 4) { 1868c2ecf20Sopenharmony_ci dma_outb(0, DMA2_MASK_REG); /* This may not be enabled */ 1878c2ecf20Sopenharmony_ci dma_outb(ucDmaCmd, DMA2_CMD_REG); /* Enable group */ 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci if (dmanr <= 3) { 1908c2ecf20Sopenharmony_ci dma_outb(dmanr, DMA1_MASK_REG); 1918c2ecf20Sopenharmony_ci dma_outb(ucDmaCmd, DMA1_CMD_REG); /* Enable group */ 1928c2ecf20Sopenharmony_ci } else { 1938c2ecf20Sopenharmony_ci dma_outb(dmanr & 3, DMA2_MASK_REG); 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic __inline__ void disable_dma(unsigned int dmanr) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci if (dmanr <= 3) 2008c2ecf20Sopenharmony_ci dma_outb(dmanr | 4, DMA1_MASK_REG); 2018c2ecf20Sopenharmony_ci else 2028c2ecf20Sopenharmony_ci dma_outb((dmanr & 3) | 4, DMA2_MASK_REG); 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci/* Clear the 'DMA Pointer Flip Flop'. 2068c2ecf20Sopenharmony_ci * Write 0 for LSB/MSB, 1 for MSB/LSB access. 2078c2ecf20Sopenharmony_ci * Use this once to initialize the FF to a known state. 2088c2ecf20Sopenharmony_ci * After that, keep track of it. :-) 2098c2ecf20Sopenharmony_ci * --- In order to do that, the DMA routines below should --- 2108c2ecf20Sopenharmony_ci * --- only be used while interrupts are disabled! --- 2118c2ecf20Sopenharmony_ci */ 2128c2ecf20Sopenharmony_cistatic __inline__ void clear_dma_ff(unsigned int dmanr) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci if (dmanr <= 3) 2158c2ecf20Sopenharmony_ci dma_outb(0, DMA1_CLEAR_FF_REG); 2168c2ecf20Sopenharmony_ci else 2178c2ecf20Sopenharmony_ci dma_outb(0, DMA2_CLEAR_FF_REG); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci/* set mode (above) for a specific DMA channel */ 2218c2ecf20Sopenharmony_cistatic __inline__ void set_dma_mode(unsigned int dmanr, char mode) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci if (dmanr <= 3) 2248c2ecf20Sopenharmony_ci dma_outb(mode | dmanr, DMA1_MODE_REG); 2258c2ecf20Sopenharmony_ci else 2268c2ecf20Sopenharmony_ci dma_outb(mode | (dmanr & 3), DMA2_MODE_REG); 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci/* Set only the page register bits of the transfer address. 2308c2ecf20Sopenharmony_ci * This is used for successive transfers when we know the contents of 2318c2ecf20Sopenharmony_ci * the lower 16 bits of the DMA current address register, but a 64k boundary 2328c2ecf20Sopenharmony_ci * may have been crossed. 2338c2ecf20Sopenharmony_ci */ 2348c2ecf20Sopenharmony_cistatic __inline__ void set_dma_page(unsigned int dmanr, int pagenr) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci switch (dmanr) { 2378c2ecf20Sopenharmony_ci case 0: 2388c2ecf20Sopenharmony_ci dma_outb(pagenr, DMA_LO_PAGE_0); 2398c2ecf20Sopenharmony_ci dma_outb(pagenr >> 8, DMA_HI_PAGE_0); 2408c2ecf20Sopenharmony_ci break; 2418c2ecf20Sopenharmony_ci case 1: 2428c2ecf20Sopenharmony_ci dma_outb(pagenr, DMA_LO_PAGE_1); 2438c2ecf20Sopenharmony_ci dma_outb(pagenr >> 8, DMA_HI_PAGE_1); 2448c2ecf20Sopenharmony_ci break; 2458c2ecf20Sopenharmony_ci case 2: 2468c2ecf20Sopenharmony_ci dma_outb(pagenr, DMA_LO_PAGE_2); 2478c2ecf20Sopenharmony_ci dma_outb(pagenr >> 8, DMA_HI_PAGE_2); 2488c2ecf20Sopenharmony_ci break; 2498c2ecf20Sopenharmony_ci case 3: 2508c2ecf20Sopenharmony_ci dma_outb(pagenr, DMA_LO_PAGE_3); 2518c2ecf20Sopenharmony_ci dma_outb(pagenr >> 8, DMA_HI_PAGE_3); 2528c2ecf20Sopenharmony_ci break; 2538c2ecf20Sopenharmony_ci case 5: 2548c2ecf20Sopenharmony_ci dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5); 2558c2ecf20Sopenharmony_ci dma_outb(pagenr >> 8, DMA_HI_PAGE_5); 2568c2ecf20Sopenharmony_ci break; 2578c2ecf20Sopenharmony_ci case 6: 2588c2ecf20Sopenharmony_ci dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6); 2598c2ecf20Sopenharmony_ci dma_outb(pagenr >> 8, DMA_HI_PAGE_6); 2608c2ecf20Sopenharmony_ci break; 2618c2ecf20Sopenharmony_ci case 7: 2628c2ecf20Sopenharmony_ci dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7); 2638c2ecf20Sopenharmony_ci dma_outb(pagenr >> 8, DMA_HI_PAGE_7); 2648c2ecf20Sopenharmony_ci break; 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci} 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci/* Set transfer address & page bits for specific DMA channel. 2698c2ecf20Sopenharmony_ci * Assumes dma flipflop is clear. 2708c2ecf20Sopenharmony_ci */ 2718c2ecf20Sopenharmony_cistatic __inline__ void set_dma_addr(unsigned int dmanr, unsigned int phys) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci if (dmanr <= 3) { 2748c2ecf20Sopenharmony_ci dma_outb(phys & 0xff, 2758c2ecf20Sopenharmony_ci ((dmanr & 3) << 1) + IO_DMA1_BASE); 2768c2ecf20Sopenharmony_ci dma_outb((phys >> 8) & 0xff, 2778c2ecf20Sopenharmony_ci ((dmanr & 3) << 1) + IO_DMA1_BASE); 2788c2ecf20Sopenharmony_ci } else { 2798c2ecf20Sopenharmony_ci dma_outb((phys >> 1) & 0xff, 2808c2ecf20Sopenharmony_ci ((dmanr & 3) << 2) + IO_DMA2_BASE); 2818c2ecf20Sopenharmony_ci dma_outb((phys >> 9) & 0xff, 2828c2ecf20Sopenharmony_ci ((dmanr & 3) << 2) + IO_DMA2_BASE); 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci set_dma_page(dmanr, phys >> 16); 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for 2898c2ecf20Sopenharmony_ci * a specific DMA channel. 2908c2ecf20Sopenharmony_ci * You must ensure the parameters are valid. 2918c2ecf20Sopenharmony_ci * NOTE: from a manual: "the number of transfers is one more 2928c2ecf20Sopenharmony_ci * than the initial word count"! This is taken into account. 2938c2ecf20Sopenharmony_ci * Assumes dma flip-flop is clear. 2948c2ecf20Sopenharmony_ci * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_cistatic __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) 2978c2ecf20Sopenharmony_ci{ 2988c2ecf20Sopenharmony_ci count--; 2998c2ecf20Sopenharmony_ci if (dmanr <= 3) { 3008c2ecf20Sopenharmony_ci dma_outb(count & 0xff, 3018c2ecf20Sopenharmony_ci ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE); 3028c2ecf20Sopenharmony_ci dma_outb((count >> 8) & 0xff, 3038c2ecf20Sopenharmony_ci ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE); 3048c2ecf20Sopenharmony_ci } else { 3058c2ecf20Sopenharmony_ci dma_outb((count >> 1) & 0xff, 3068c2ecf20Sopenharmony_ci ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE); 3078c2ecf20Sopenharmony_ci dma_outb((count >> 9) & 0xff, 3088c2ecf20Sopenharmony_ci ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE); 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci/* Get DMA residue count. After a DMA transfer, this 3148c2ecf20Sopenharmony_ci * should return zero. Reading this while a DMA transfer is 3158c2ecf20Sopenharmony_ci * still in progress will return unpredictable results. 3168c2ecf20Sopenharmony_ci * If called before the channel has been used, it may return 1. 3178c2ecf20Sopenharmony_ci * Otherwise, it returns the number of _bytes_ left to transfer. 3188c2ecf20Sopenharmony_ci * 3198c2ecf20Sopenharmony_ci * Assumes DMA flip-flop is clear. 3208c2ecf20Sopenharmony_ci */ 3218c2ecf20Sopenharmony_cistatic __inline__ int get_dma_residue(unsigned int dmanr) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci unsigned int io_port = (dmanr <= 3) 3248c2ecf20Sopenharmony_ci ? ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE 3258c2ecf20Sopenharmony_ci : ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* using short to get 16-bit wrap around */ 3288c2ecf20Sopenharmony_ci unsigned short count; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci count = 1 + dma_inb(io_port); 3318c2ecf20Sopenharmony_ci count += dma_inb(io_port) << 8; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci return (dmanr <= 3) ? count : (count << 1); 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci/* These are in kernel/dma.c: */ 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci/* reserve a DMA channel */ 3398c2ecf20Sopenharmony_ciextern int request_dma(unsigned int dmanr, const char *device_id); 3408c2ecf20Sopenharmony_ci/* release it again */ 3418c2ecf20Sopenharmony_ciextern void free_dma(unsigned int dmanr); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 3448c2ecf20Sopenharmony_ciextern int isa_dma_bridge_buggy; 3458c2ecf20Sopenharmony_ci#else 3468c2ecf20Sopenharmony_ci#define isa_dma_bridge_buggy (0) 3478c2ecf20Sopenharmony_ci#endif 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci#endif /* __KERNEL__ */ 3508c2ecf20Sopenharmony_ci#endif /* _ASM_POWERPC_DMA_H */ 351