/** * Set retval to internal ID for requested Native Feature, * or zero if feature is unknown/unsupported. * * Return true if caller is to proceed normally, * false if there was an exception. */ bool NatFeat_ID(Uint32 stack, Uint32 *retval) { const char *name; Uint32 ptr; int i; ptr = STMemory_ReadLong(stack); if (!STMemory_ValidArea(ptr, FEATNAME_MAX)) { M68000_BusError(ptr, BUS_ERROR_READ); return false; } name = (const char *)STRAM_ADDR(ptr); Dprintf(("NF ID(0x%x)\n", ptr)); Dprintf((" \"%s\"\n", name)); for (i = 0; i < ARRAYSIZE(features); i++) { if (strcmp(features[i].name, name) == 0) { *retval = IDX2MASTERID(i); return true; } } /* unknown feature */ *retval = 0; return true; }
/** * XBIOS remote control interface for Hatari * Call 255 */ static bool XBios_HatariControl(Uint32 Params) { const char *pText; pText = (const char *)STRAM_ADDR(STMemory_ReadLong(Params)); LOG_TRACE(TRACE_OS_XBIOS, "XBIOS 0x%02X HatariControl(%s) at PC 0x%X\n", HATARI_CONTROL_OPCODE, pText, M68000_GetPC()); if (!bXBiosCommands) return false; Control_ProcessBuffer(pText); Regs[REG_D0] = 0; return true; }
/** * BIOS Read/Write disk sector * Call 4 */ static void Bios_RWabs(Uint32 Params) { Uint32 pBuffer; Uint16 RWFlag, Number, RecNo, Dev; /* Read details from stack */ RWFlag = STMemory_ReadWord(Params); pBuffer = STMemory_ReadLong(Params+SIZE_WORD); Number = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG); RecNo = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG+SIZE_WORD); Dev = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG+SIZE_WORD+SIZE_WORD); LOG_TRACE(TRACE_OS_BIOS, "BIOS 0x04 Rwabs(%d,0x%lX,%d,%d,%i)\n", RWFlag, STRAM_ADDR(pBuffer), Number, RecNo, Dev); }
static bool nf_stderr(Uint32 stack, Uint32 subid, Uint32 *retval) { const char *str; Uint32 ptr; ptr = STMemory_ReadLong(stack); //Dprintf(("NF stderr(0x%x)\n", ptr)); if (!STMemory_ValidArea(ptr, 1)) { M68000_BusError(ptr, BUS_ERROR_READ); return false; } str = (const char *)STRAM_ADDR(ptr); *retval = fprintf(stderr, "%s", str); fflush(stderr); return true; }
/** * BIOS Read/Write disk sector * Call 4 */ static bool Bios_RWabs(Uint32 Params) { Uint32 pBuffer; Uint16 RWFlag, Number, RecNo, Dev; /* Read details from stack */ RWFlag = STMemory_ReadWord(Params+SIZE_WORD); pBuffer = STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD); Number = STMemory_ReadWord(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG); RecNo = STMemory_ReadWord(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG+SIZE_WORD); Dev = STMemory_ReadWord(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG+SIZE_WORD+SIZE_WORD); HATARI_TRACE(HATARI_TRACE_OS_BIOS, "BIOS RWabs %i,%d,0x%lX,%d,%d\n", Dev, RWFlag, STRAM_ADDR(pBuffer), RecNo, Number); return FALSE; }
static bool nf_name(Uint32 stack, Uint32 subid, Uint32 *retval) { Uint32 ptr, len; const char *str; char *buf; ptr = STMemory_ReadLong(stack); len = STMemory_ReadLong(stack + SIZE_LONG); Dprintf(("NF name[%d](0x%x, %d)\n", subid, ptr, len)); if (!STMemory_ValidArea(ptr, len)) { M68000_BusError(ptr, BUS_ERROR_WRITE); return false; } if (subid) { str = PROG_NAME; } else { str = "Hatari"; } buf = (char *)STRAM_ADDR(ptr); *retval = snprintf(buf, len, "%s", str); return true; }
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 unsigned long atari_dma_xfer_len( unsigned long wanted_len, Scsi_Cmnd *cmd, int write_flag ) { unsigned long possible_len, limit; #ifndef CONFIG_TT_DMA_EMUL if (MACH_IS_HADES) /* Hades has no SCSI DMA at all :-( Always force use of PIO */ return( 0 ); #endif if (IS_A_TT()) /* TT SCSI DMA can transfer arbitrary #bytes */ return( wanted_len ); /* ST DMA chip is stupid -- only multiples of 512 bytes! (and max. * 255*512 bytes, but this should be enough) * * ++roman: Aaargl! Another Falcon-SCSI problem... There are some commands * that return a number of bytes which cannot be known beforehand. In this * case, the given transfer length is an "allocation length". Now it * can happen that this allocation length is a multiple of 512 bytes and * the DMA is used. But if not n*512 bytes really arrive, some input data * will be lost in the ST-DMA's FIFO :-( Thus, we have to distinguish * between commands that do block transfers and those that do byte * transfers. But this isn't easy... there are lots of vendor specific * commands, and the user can issue any command via the * SCSI_IOCTL_SEND_COMMAND. * * The solution: We classify SCSI commands in 1) surely block-mode cmd.s, * 2) surely byte-mode cmd.s and 3) cmd.s with unknown mode. In case 1) * and 3), the thing to do is obvious: allow any number of blocks via DMA * or none. In case 2), we apply some heuristic: Byte mode is assumed if * the transfer (allocation) length is < 1024, hoping that no cmd. not * explicitly known as byte mode have such big allocation lengths... * BTW, all the discussion above applies only to reads. DMA writes are * unproblematic anyways, since the targets aborts the transfer after * receiving a sufficient number of bytes. * * Another point: If the transfer is from/to an non-ST-RAM address, we * use the dribble buffer and thus can do only STRAM_BUFFER_SIZE bytes. */ if (write_flag) { /* Write operation can always use the DMA, but the transfer size must * be rounded up to the next multiple of 512 (atari_dma_setup() does * this). */ possible_len = wanted_len; } else { /* Read operations: if the wanted transfer length is not a multiple of * 512, we cannot use DMA, since the ST-DMA cannot split transfers * (no interrupt on DMA finished!) */ if (wanted_len & 0x1ff) possible_len = 0; else { /* Now classify the command (see above) and decide whether it is * allowed to do DMA at all */ switch( falcon_classify_cmd( cmd )) { case CMD_SURELY_BLOCK_MODE: possible_len = wanted_len; break; case CMD_SURELY_BYTE_MODE: possible_len = 0; /* DMA prohibited */ break; case CMD_MODE_UNKNOWN: default: /* For unknown commands assume block transfers if the transfer * size/allocation length is >= 1024 */ possible_len = (wanted_len < 1024) ? 0 : wanted_len; break; } } } /* Last step: apply the hard limit on DMA transfers */ limit = (atari_dma_buffer && !STRAM_ADDR( virt_to_phys(cmd->SCp.ptr) )) ? STRAM_BUFFER_SIZE : 255*512; if (possible_len > limit) possible_len = limit; if (possible_len != wanted_len) DMA_PRINTK("Sorry, must cut DMA transfer size to %ld bytes " "instead of %ld\n", possible_len, wanted_len); return( possible_len ); }
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; }
/** * Output AES call info, including some of args */ static void AES_OpcodeInfo(FILE *fp, Uint16 opcode) { int code = opcode - 10; fprintf(fp, "AES call %3hd ", opcode); if (code >= 0 && code < ARRAYSIZE(AESName_10) && AESName_10[code]) { bool first = true; int i, items; fprintf(fp, "%s(", AESName_10[code]); items = 0; /* there are so few of these that linear search is fine */ for (i = 0; i < ARRAYSIZE(AESStrings); i++) { /* something that can be shown? */ if (AESStrings[i].code == opcode) { items = AESStrings[i].count; break; } } /* addrin array size in longs enough for items? */ if (items > 0 && items <= STMemory_ReadWord(AESControl+SIZE_WORD*3)) { const char *str; fputs("addrin: ", fp); for (i = 0; i < items; i++) { if (first) first = false; else fputs(", ", fp); str = (const char *)STRAM_ADDR(STMemory_ReadLong(AESAddrin+SIZE_LONG*i)); fprintf(fp, "\"%s\"", str); } } /* intin array size in words */ items = STMemory_ReadWord(AESControl+SIZE_WORD*1); if (items > 0) { if (!first) { fputs(", ", fp); first = true; } fputs("intin: ", fp); for (i = 0; i < items; i++) { if (first) first = false; else fputs(",", fp); fprintf(fp, "0x%x", STMemory_ReadWord(AESIntin+SIZE_WORD*i)); } } fputs(")\n", fp); } else fputs("???\n", fp); fflush(fp); }