|
@@ -216,3 +216,102 @@ static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
|
|
*/
|
|
*/
|
|
static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
|
|
static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
|
|
{
|
|
{
|
|
|
|
+ switch(dmanr) {
|
|
|
|
+ case 0:
|
|
|
|
+ dma_outb(pagenr, DMA_PAGE_0);
|
|
|
|
+ break;
|
|
|
|
+ case 1:
|
|
|
|
+ dma_outb(pagenr, DMA_PAGE_1);
|
|
|
|
+ break;
|
|
|
|
+ case 2:
|
|
|
|
+ dma_outb(pagenr, DMA_PAGE_2);
|
|
|
|
+ break;
|
|
|
|
+ case 3:
|
|
|
|
+ dma_outb(pagenr, DMA_PAGE_3);
|
|
|
|
+ break;
|
|
|
|
+ case 5:
|
|
|
|
+ dma_outb(pagenr & 0xfe, DMA_PAGE_5);
|
|
|
|
+ break;
|
|
|
|
+ case 6:
|
|
|
|
+ dma_outb(pagenr & 0xfe, DMA_PAGE_6);
|
|
|
|
+ break;
|
|
|
|
+ case 7:
|
|
|
|
+ dma_outb(pagenr & 0xfe, DMA_PAGE_7);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/* Set transfer address & page bits for specific DMA channel.
|
|
|
|
+ * Assumes dma flipflop is clear.
|
|
|
|
+ */
|
|
|
|
+static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
|
|
|
|
+{
|
|
|
|
+ set_dma_page(dmanr, a>>16);
|
|
|
|
+ if (dmanr <= 3) {
|
|
|
|
+ dma_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
|
|
|
|
+ dma_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
|
|
|
|
+ } else {
|
|
|
|
+ dma_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
|
|
|
|
+ dma_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/* Set transfer size (max 64k for DMA0..3, 128k for DMA5..7) for
|
|
|
|
+ * a specific DMA channel.
|
|
|
|
+ * You must ensure the parameters are valid.
|
|
|
|
+ * NOTE: from a manual: "the number of transfers is one more
|
|
|
|
+ * than the initial word count"! This is taken into account.
|
|
|
|
+ * Assumes dma flip-flop is clear.
|
|
|
|
+ * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7.
|
|
|
|
+ */
|
|
|
|
+static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
|
|
|
|
+{
|
|
|
|
+ count--;
|
|
|
|
+ if (dmanr <= 3) {
|
|
|
|
+ dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
|
|
|
|
+ dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
|
|
|
|
+ } else {
|
|
|
|
+ dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
|
|
|
|
+ dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/* Get DMA residue count. After a DMA transfer, this
|
|
|
|
+ * should return zero. Reading this while a DMA transfer is
|
|
|
|
+ * still in progress will return unpredictable results.
|
|
|
|
+ * If called before the channel has been used, it may return 1.
|
|
|
|
+ * Otherwise, it returns the number of _bytes_ left to transfer.
|
|
|
|
+ *
|
|
|
|
+ * Assumes DMA flip-flop is clear.
|
|
|
|
+ */
|
|
|
|
+static __inline__ int get_dma_residue(unsigned int dmanr)
|
|
|
|
+{
|
|
|
|
+ unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE
|
|
|
|
+ : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE;
|
|
|
|
+
|
|
|
|
+ /* using short to get 16-bit wrap around */
|
|
|
|
+ unsigned short count;
|
|
|
|
+
|
|
|
|
+ count = 1 + dma_inb(io_port);
|
|
|
|
+ count += dma_inb(io_port) << 8;
|
|
|
|
+
|
|
|
|
+ return (dmanr<=3)? count : (count<<1);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/* These are in kernel/dma.c: */
|
|
|
|
+extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */
|
|
|
|
+extern void free_dma(unsigned int dmanr); /* release it again */
|
|
|
|
+
|
|
|
|
+/* From PCI */
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_PCI
|
|
|
|
+extern int isa_dma_bridge_buggy;
|
|
|
|
+#else
|
|
|
|
+#define isa_dma_bridge_buggy (0)
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#endif /* _ASM_DMA_H */
|