static void start_print( int device ) { struct slm *sip = &slm_info[device]; unsigned char *cmd; unsigned long paddr; int i; stdma_lock( slm_interrupt, NULL ); CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun ); cmd = slmprint_cmd; paddr = virt_to_phys( SLMBuffer ); dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 ); DISABLE_IRQ(); /* Low on A1 */ dma_wd.dma_mode_status = 0x88; MFPDELAY(); /* send the command bytes except the last */ for( i = 0; i < 5; ++i ) { DMA_LONG_WRITE( *cmd++, 0x8a ); udelay(20); if (!acsi_wait_for_IRQ( HZ/2 )) { SLMError = 1; return; /* timeout */ } } /* last command byte */ DMA_LONG_WRITE( *cmd++, 0x82 ); MFPDELAY(); /* set DMA address */ set_dma_addr( paddr ); /* program DMA for write and select sector counter reg */ dma_wd.dma_mode_status = 0x192; MFPDELAY(); /* program for 255*512 bytes and start DMA */ DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 ); #ifndef SLM_CONT_CNT_REPROG SLMCurAddr = paddr; SLMEndAddr = paddr + SLMSliceSize + SLM_DMA_INT_OFFSET; #endif START_TIMER( DMA_STARTUP_TIME + DMA_TIME_FOR( SLMSliceSize )); #if !defined(SLM_CONT_CNT_REPROG) && defined(DEBUG) printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n", SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) ); #endif ENABLE_IRQ(); }
/* We have a good packet(s), get it/them out of the buffers. */ static void bionet_poll_rx(struct net_device *dev) { struct net_local *lp = netdev_priv(dev); int boguscount = 10; int pkt_len, status; unsigned long flags; local_irq_save(flags); /* ++roman: Take care at locking the ST-DMA... This must be done with ints * off, since otherwise an int could slip in between the question and the * locking itself, and then we'd go to sleep... And locking itself is * necessary to keep the floppy_change timer from working with ST-DMA * registers. */ if (stdma_islocked()) { local_irq_restore(flags); return; } stdma_lock(bionet_intr, NULL); DISABLE_IRQ(); local_irq_restore(flags); if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++; while(boguscount--) { status = get_frame((unsigned long)phys_nic_packet, 0); if( status == 0 ) break; /* Good packet... */ dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0); pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo; lp->poll_time = bionet_min_poll_time; /* fast poll */ if( pkt_len >= 60 && pkt_len <= 1520 ) { /* ^^^^ war 1514 KHL */ /* Malloc up new buffer. */ struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 ); if (skb == NULL) { printk("%s: Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; break; } skb->dev = dev; skb_reserve( skb, 2 ); /* 16 Byte align */ skb_put( skb, pkt_len ); /* make room */ /* 'skb->data' points to the start of sk_buff data area. */ memcpy(skb->data, nic_packet->buffer, pkt_len); skb->protocol = eth_type_trans( skb, dev ); netif_rx(skb); dev->last_rx = jiffies; lp->stats.rx_packets++; lp->stats.rx_bytes+=pkt_len; /* If any worth-while packets have been received, dev_rint() has done a mark_bh(INET_BH) for us and will work on them when we get to the bottom-half routine. */ if (bionet_debug >1) { u_char *data = nic_packet->buffer, *p; int i; printk( "%s: RX pkt type 0x%4x from ", dev->name, ((u_short *)data)[6]); for( p = &data[6], i = 0; i < 6; i++ ) printk("%02x%s", *p++,i != 5 ? ":" : "" ); printk(" to "); for( p = data, i = 0; i < 6; i++ ) printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); printk( "%s: ", dev->name ); printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" " %02x%02x%02x%02x len %d\n", data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], data[28], data[29], data[30], data[31], data[32], data[33], pkt_len ); } } else { printk(" Packet has wrong length: %04d bytes\n", pkt_len); lp->stats.rx_errors++; } } stdma_release(); ENABLE_IRQ(); return; }
unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data, unsigned long count, int dir ) { unsigned long addr = virt_to_phys( data ); DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, " "dir = %d\n", instance->host_no, data, addr, count, dir); if (!IS_A_TT() && !STRAM_ADDR(addr)) { /* If we have a non-DMAable address on a Falcon, use the dribble * buffer; 'orig_addr' != 0 in the read case tells the interrupt * handler to copy data from the dribble buffer to the originally * wanted address. */ if (dir) memcpy( atari_dma_buffer, data, count ); else atari_dma_orig_addr = data; addr = atari_dma_phys_buffer; } atari_dma_startaddr = addr; /* Needed for calculating residual later. */ /* Cache cleanup stuff: On writes, push any dirty cache out before sending * it to the peripheral. (Must be done before DMA setup, since at least * the ST-DMA begins to fill internal buffers right after setup. For * reads, invalidate any cache, may be altered after DMA without CPU * knowledge. * * ++roman: For the Medusa, there's no need at all for that cache stuff, * because the hardware does bus snooping (fine!). */ dma_cache_maintenance( addr, count, dir ); if (count == 0) printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n"); if (IS_A_TT()) { tt_scsi_dma.dma_ctrl = dir; SCSI_DMA_WRITE_P( dma_addr, addr ); SCSI_DMA_WRITE_P( dma_cnt, count ); tt_scsi_dma.dma_ctrl = dir | 2; } else { /* ! IS_A_TT */ /* set address */ SCSI_DMA_SETADR( addr ); /* toggle direction bit to clear FIFO and set DMA direction */ dir <<= 8; st_dma.dma_mode_status = 0x90 | dir; st_dma.dma_mode_status = 0x90 | (dir ^ 0x100); st_dma.dma_mode_status = 0x90 | dir; udelay(40); /* On writes, round up the transfer length to the next multiple of 512 * (see also comment at atari_dma_xfer_len()). */ st_dma.fdc_acces_seccount = (count + (dir ? 511 : 0)) >> 9; udelay(40); st_dma.dma_mode_status = 0x10 | dir; udelay(40); /* need not restore value of dir, only boolean value is tested */ atari_dma_active = 1; } return( count ); }
static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev) { struct net_local *lp = netdev_priv(dev); unsigned long flags; /* Block a timer-based transmit from overlapping. This could better be * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ local_irq_save(flags); if (stdma_islocked()) { local_irq_restore(flags); lp->stats.tx_errors++; } else { int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned long buf = virt_to_phys(skb->data); int stat; stdma_lock(bionet_intr, NULL); local_irq_restore(flags); if( !STRAM_ADDR(buf+length-1) ) { memcpy(nic_packet->buffer, skb->data, length); buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer; } if (bionet_debug >1) { u_char *data = nic_packet->buffer, *p; int i; printk( "%s: TX pkt type 0x%4x from ", dev->name, ((u_short *)data)[6]); for( p = &data[6], i = 0; i < 6; i++ ) printk("%02x%s", *p++,i != 5 ? ":" : "" ); printk(" to "); for( p = data, i = 0; i < 6; i++ ) printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); printk( "%s: ", dev->name ); printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" " %02x%02x%02x%02x len %d\n", data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], data[28], data[29], data[30], data[31], data[32], data[33], length ); } dma_cache_maintenance(buf, length, 1); stat = hardware_send_packet(buf, length); ENABLE_IRQ(); stdma_release(); dev->trans_start = jiffies; dev->tbusy = 0; lp->stats.tx_packets++; lp->stats.tx_bytes+=length; } dev_kfree_skb(skb); return 0; }