⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 maple.c

📁 newos is new operation system
💻 C
字号:
/*** Copyright 2001, Travis Geiselbrecht. All rights reserved.** Distributed under the terms of the NewOS License.*/#include <kernel/kernel.h>#include <kernel/vfs.h>#include <kernel/debug.h>#include <kernel/sem.h>#include <kernel/lock.h>#include <kernel/heap.h>#include <kernel/vm.h>#include <kernel/arch/cpu.h>#include <kernel/fs/devfs.h>#include <string.h>#include <stdio.h>#include <kernel/dev/arch/sh4/maple/maple_bus.h>#define MAPLE(x) (*(volatile unsigned int *)((0xa05f6c00)+(x)))#define DMA_BUF_SIZE (128*1024)struct maple_config {	struct maple_config *next;	char *full_path;	maple_devinfo_t cfg;	uint8 port;	uint8 unit;};struct maple_bus {	region_id dma_region_id;	void *dma_buffer;	int func_codes[4][6];	struct maple_config *maple_list;	mutex lock;} mbus;static uint8 maple_create_addr(uint8 port, uint8 unit){	uint8 addr;	if(port > 3 || unit > 5)		return -1;	addr = port << 6;	if(unit != 0) {		addr |= (1 << (unit - 1)) & 0x1f;	} else {		addr |= 0x20;	}	return addr;}static uint32 *maple_add_trans(struct maple_bus *bus, maple_tdesc_t *tdesc, uint32 *buf){	int i;	// build the transfer descriptor's two words	*buf++ = tdesc->length | (tdesc->port << 16) | (tdesc->lastdesc << 31);	*buf++ = ((uint32)tdesc->recvaddr) & 0xfffffff;	// do each of the frames in this transfer	for(i=0; i<tdesc->numframes; i++) {		maple_frame_t *frame = &tdesc->frames[i];		*buf++ = (frame->cmd & 0xff) | (frame->to << 8) |			(frame->from << 16) | (frame->datalen << 24);		/* copy data over */		if(frame->datalen > 0) {			memcpy(buf, frame->data, frame->datalen * 4);			buf += frame->datalen;		}	}	return buf;}static int maple_dodma(struct maple_bus *bus){	// start the dma	MAPLE(0x18) = 1;	// wait for the dma to be done	while(MAPLE(0x18) & 0x1)		;	return 0;}static void maple_read_frame(uint32 *_buf, maple_frame_t *frame){	uint8	*buf = (uint8 *)_buf;	frame->cmd = buf[0];	frame->to = buf[1];	frame->from = buf[2];	frame->datalen = buf[3];	frame->data = &buf[4];}static int maple_docmd(struct maple_bus *bus, int8 cmd, uint8 addr, uint8 datalen, void *data, maple_frame_t *retframe){	uint32 *sendbuf, *recvbuf;	maple_tdesc_t	tdesc;	maple_frame_t	frame;	sendbuf = (uint32 *)bus->dma_buffer;	recvbuf = sendbuf + 256;	// build the transfer descriptor with one frame in it	tdesc.lastdesc = 1;	tdesc.port = addr >> 6;	tdesc.length = datalen;	tdesc.recvaddr = recvbuf;	tdesc.numframes = 1;	tdesc.frames = &frame;	frame.cmd = cmd;	frame.data = data;	frame.datalen = datalen;	frame.from = tdesc.port << 6;	frame.to = addr;	// set the dma ptr	MAPLE(0x04) = ((uint32)sendbuf) & 0xfffffff;	maple_add_trans(bus, &tdesc, sendbuf);	MAPLE(0x18) = 0;	if(maple_dodma(bus) == 0) {		maple_read_frame(recvbuf, retframe);		return 0;	}	return -1;}static int maple_open(dev_ident ident, dev_cookie *_cookie){	struct maple_config *c = (struct maple_config *)ident;	dprintf("maple_open: entry on '%s'\n", c->full_path);	*_cookie = c;	return 0;}static int maple_freecookie(dev_cookie _cookie){	return 0;}static int maple_seek(dev_cookie cookie, off_t pos, seek_type st){	dprintf("maple_seek: entry\n");	return ERR_NOT_ALLOWED;}static int maple_close(dev_cookie _cookie){	dprintf("maple_close: entry\n");	return 0;}static int maple_read(dev_cookie cookie, void *buf, off_t pos, ssize_t len){	dprintf("maple_read: entry\n");	return ERR_NOT_ALLOWED;}static int maple_write(dev_cookie cookie, const void *buf, off_t pos, ssize_t len){	dprintf("maple_write: entry, len = %d\n", len);	return ERR_NOT_ALLOWED;}static int maple_ioctl(dev_cookie _cookie, int op, void *buf, size_t len){	int err = 0;	struct maple_config *cookie = (struct maple_config *)_cookie;	switch(op) {		case MAPLE_IOCTL_GET_FUNC:			*(uint32 *)buf = mbus.func_codes[cookie->port][cookie->unit];			break;		case MAPLE_IOCTL_SEND_COMMAND: {			maple_command *cmd = buf;			int8 address = maple_create_addr(cookie->port, cookie->unit);			mutex_lock(&mbus.lock);			err = maple_docmd(&mbus, cmd->cmd, address, cmd->outdatalen, cmd->outdata, cmd->retframe);			if(err == NO_ERROR) {				// copy the data back out				memcpy(cmd->indata, cmd->retframe->data, min(cmd->retframe->datalen * 4, cmd->indatalen * 4));			}			mutex_unlock(&mbus.lock);			break;		}		default:			err = -1;	}	return err;}static int maple_scan_bus(struct maple_bus *bus){	int err;	int port, unit;	maple_frame_t frame;	memset(&bus->func_codes[0][0], 0, sizeof(bus->func_codes));	for(port = 0; port < 4; port++) {		for(unit = 0; unit < 6; unit++) {			err = maple_docmd(bus, MAPLE_COMMAND_DEVINFO, maple_create_addr(port, unit), 0, NULL, &frame);			if(err < 0)				return err;			if(frame.cmd == MAPLE_RESPONSE_DEVINFO) {				struct maple_config *cfg;				char char_buf[SYS_MAX_PATH_LEN];				cfg = (struct maple_config *)kmalloc(sizeof(struct maple_config));				if(!cfg)					return ERR_NO_MEMORY;				memcpy(&cfg->cfg, frame.data, sizeof(cfg->cfg));				cfg->cfg.product_name[29] = 0;				dprintf("port %d unit %d responded to device query!\n", port, unit);				dprintf("%c%c:  %s  (0x%x)\n", 'a'+port, '0'+unit, cfg->cfg.product_name, cfg->cfg.func);				bus->func_codes[port][unit] = cfg->cfg.func;				cfg->port = port;				cfg->unit = unit;				sprintf(char_buf, "bus/maple/%d/%d/ctrl", port, unit);				cfg->full_path = kmalloc(strlen(char_buf)+1);				strcpy(cfg->full_path, char_buf);				cfg->next = bus->maple_list;				bus->maple_list = cfg;			} else {				bus->func_codes[port][unit] = 0;			}		}	}	return 0;}static int maple_init(struct maple_bus *bus){	void *foo = NULL;	int err;	bus->dma_region_id = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "maple_bus_dma_region", &foo,		REGION_ADDR_ANY_ADDRESS, DMA_BUF_SIZE, REGION_WIRING_WIRED_CONTIG, LOCK_RW|LOCK_KERNEL);	if(bus->dma_region_id < 0)		panic("could not create maple bus dma region\n");	mutex_init(&bus->lock, "maple_bus_lock");	vm_get_page_mapping(vm_get_kernel_aspace_id(), (addr_t)foo, (addr_t *)&bus->dma_buffer);	bus->dma_buffer = (void *)PHYS_ADDR_TO_P2(bus->dma_buffer);	memset(bus->dma_buffer, 0, DMA_BUF_SIZE);	dprintf("maple_init: created dma area at P2 addr 0x%x\n", bus->dma_buffer);	/* reset hardware */	MAPLE(0x8c) = 0x6155404f;	MAPLE(0x10) = 0;	MAPLE(0x80) = (50000 << 16) | 0; // set the timeout and bitrate to 2Mbps	/* enable the bus */	MAPLE(0x14) = 1;	return 0;error1://	vm_delete_area(fs->bus.dma_area);error:	return err;}struct dev_calls maple_hooks = {	&maple_open,	&maple_close,	&maple_freecookie,	&maple_seek,	&maple_ioctl,	&maple_read,	&maple_write,	/* cannot page from maple devices */	NULL,	NULL,	NULL};int maple_bus_init(kernel_args *ka){	struct maple_config *c;	memset(&mbus, 0, sizeof(mbus));	maple_init(&mbus);	maple_scan_bus(&mbus);	// create device nodes	for(c = mbus.maple_list; c; c = c->next) {		devfs_publish_device(c->full_path, c, &maple_hooks);	}	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -