예제 #1
0
파일: hd.c 프로젝트: wwssllabcd/myOS
/**
 * <Ring 1> This routine handles DEV_READ and DEV_WRITE message.
 *
 * @param p Message ptr.
 *****************************************************************************/
PRIVATE void hd_rdwt(MESSAGE * p)
{
    // p->DEVICE 為 0x20,也就是 hd2a
    int pDev = p->DEVICE;
    int drive = DRV_OF_DEV(p->DEVICE);
    u64 pos = p->POSITION;
    assert((pos >> SECTOR_SIZE_SHIFT) < (1 << 31));

    /**
     * We only allow to R/W from a SECTOR boundary:
     */
    assert((pos & 0x1FF) == 0);

    u32 sect_nr = (u32)(pos >> SECTOR_SIZE_SHIFT); /* pos / SECTOR_SIZE */

    //取出logic index
    int logidx = (p->DEVICE - MINOR_hd1a) % NR_SUB_PER_DRIVE;

    // 找出某個partition的LBA,
    // MAX_PRIM=9,代表Hd0~Hd9為primary的編號,超過9以上的編號都是logic
    sect_nr += p->DEVICE < MAX_PRIM ?
               hd_info[drive].primary[p->DEVICE].base :
               hd_info[drive].logical[logidx].base;

    ERIC_HD("\nHDRW=%x", sect_nr);

    struct hd_cmd cmd;
    cmd.features	= 0;
    cmd.count	= (p->CNT + SECTOR_SIZE - 1) / SECTOR_SIZE;
    cmd.lba_low	= sect_nr & 0xFF;
    cmd.lba_mid	= (sect_nr >>  8) & 0xFF;
    cmd.lba_high= (sect_nr >> 16) & 0xFF;
    cmd.device	= MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xF);
    cmd.command	= (p->type == DEV_READ) ? ATA_READ : ATA_WRITE;

    hd_cmd_out(&cmd);

    int bytes_left = p->CNT;
    void * la = (void*)va2la(p->PROC_NR, p->BUF);

    while (bytes_left) {
        //一次只讀512 byte
        int bytes = min(SECTOR_SIZE, bytes_left);

        if (p->type == DEV_READ) {
            interrupt_wait();
            port_read(REG_DATA, hdbuf, SECTOR_SIZE);
            phys_copy(la, (void*)va2la(TASK_HD, hdbuf), bytes);
        }
        else {
            if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT))
                panic("hd writing error.");

            port_write(REG_DATA, la, bytes);
            interrupt_wait();
        }
        bytes_left -= SECTOR_SIZE;
        la += SECTOR_SIZE;
    }
}
예제 #2
0
파일: main.c 프로젝트: BackupGGCode/lyos
PUBLIC void register_filesystem(MESSAGE * m){
	struct file_system * tmp;
	memcpy(va2la(TASK_FS, tmp), va2la(m->source, m->BUF), sizeof(struct file_system));
	printl("VFS: Register filesystem: name: %s\n", tmp->name);
	if (file_systems == NULL) {
		file_systems = tmp;
	}
}
예제 #3
0
파일: proc.c 프로젝트: liangbizhi/bzOS
/**************************************************************************************************
 * 					msg_send
 **************************************************************************************************
 * <Ring 0> Send a message to the dest proc. If dest is blocked waiting for the message,
 * copy the message to it and unblock dest. 
 * Otherwise the caller will be blocked and appended to the dest's sending queue.
 *
 * @param current	The caller, the sender.
 * @param dest		To whom the message is sent.
 * @param msg		Pointer to the MESSAGE struct.
 *
 * @return		0 if success.
 *************************************************************************************************/
PRIVATE int msg_send(PROCESS* current, int dest, MESSAGE* msg){
	PROCESS* sender		= current;
	PROCESS* p_dest		= proc_table + dest;

	assert(proc2pid(sender) != dest);

	if(deadlock(proc2pid(sender), dest)){			/* Is there deadlock chain? */
		panic(">>DEADLOCK<< %s->%s", sender->name, p_dest->name);
	}
	/* dest is waiting for that msg or ANY msg. */
	if((p_dest->flags & RECEIVING) && (p_dest->recv_from == proc2pid(sender) || p_dest->recv_from == ANY)){
		assert(p_dest->p_msg);
		assert(msg);
		
		phys_copy(va2la(dest, p_dest->p_msg), va2la(proc2pid(sender), msg), sizeof(MESSAGE));

		p_dest->p_msg		= 0;
		p_dest->flags		&= ~RECEIVING;		/* dest has received the message */
		p_dest->recv_from	= NO_TASK;
		unblock(p_dest);

		assert(p_dest->flags == 0);
		assert(p_dest->p_msg == 0);
		assert(p_dest->recv_from == NO_TASK);
		assert(p_dest->send_to == NO_TASK);

		assert(sender->flags == 0);
		assert(sender->p_msg == 0);
		assert(sender->recv_from == NO_TASK);
		assert(sender->send_to == NO_TASK);
	}else{	/* However, dest is not waiting for the message */
		sender->flags		|= SENDING;
		assert(sender->flags == SENDING);
		sender->send_to		= dest;
		sender->p_msg		= msg;

		/* append to the sending queue */
		PROCESS* p;
		if(p_dest->q_sending){
			p = p_dest->q_sending;
			while(p->next_sending){
				p = p->next_sending;
			}
			p->next_sending = sender;
		}else{
			p_dest->q_sending = sender;
		}
		sender->next_sending = 0;
		block(sender);

		assert(sender->flags == SENDING);
		assert(sender->p_msg != 0);
		assert(sender->recv_from == NO_TASK);
		assert(sender->send_to == dest);
	}
	return 0;
}
예제 #4
0
파일: hd.c 프로젝트: cosail/lwos
/*
 * <ring 1> this routine handles DEV_READ and DEV_WRITE message.
 *
 * @param msg - message
 */
static void hd_rdwt(MESSAGE *msg)
{
	int drive = DRV_OF_DEV(msg->DEVICE);

	u64 pos = msg->POSITION;
	assert((pos >> SECTOR_SIZE_SHIFT) < (1 << 31));

	assert((pos & 0x1ff) == 0);

	u32 sect_nr = (u32)(pos >> SECTOR_SIZE_SHIFT);
	int logidx = (msg->DEVICE - MINOR_hd1a) % NR_SUB_PER_DRIVE;
	sect_nr += msg->DEVICE < MAX_PRIM ?
		hd_info[drive].primary[msg->DEVICE].base :
		hd_info[drive].logical[logidx].base;

	struct hd_cmd cmd;
	cmd.features = 0;
	cmd.count = (msg->CNT + SECTOR_SIZE - 1) / SECTOR_SIZE;
	cmd.lba_low = sect_nr & 0xff;
	cmd.lba_mid = (sect_nr >> 8) & 0xff;
	cmd.lba_high = (sect_nr >> 16) & 0xff;
	cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xf);
	cmd.command = (msg->type == DEV_READ) ? ATA_READ : ATA_WRITE;

	hd_cmd_out(&cmd);

	int bytes_left = msg->CNT;
	void *la = (void*)va2la(msg->PROC_NR, msg->BUF);

	while (bytes_left > 0)
	{
		int bytes = min(SECTOR_SIZE, bytes_left);
		if (msg->type == DEV_READ)
		{
			interrupt_wait();
			port_read(REG_DATA, hdbuf, SECTOR_SIZE);
			phys_copy(la, (void*)va2la(TASK_HD, hdbuf), bytes);
		}
		else
		{
			if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT))
			{
				panic("hd writing error.");
			}

			port_write(REG_DATA, la, bytes);
			interrupt_wait();
		}

		bytes_left -= SECTOR_SIZE;
		la += SECTOR_SIZE;
	}
}
예제 #5
0
파일: hd.c 프로젝트: 565407548/micro_os
/*
1.函数内部需要注意:while(1),while(-1)都会执行循环体,只有while(0)时才跳出循环体
2.目前只能处理读写数据长度为SECTOR_SIZE整数倍的请求,否则会出错
*/
static void hd_rdwt(MESSAGE *message){
    int hd_index=HD_INDEX(message->device);
    int hd_part_index=HD_PART_INDEX(message->device);

    u64 position=message->position;
#ifdef DEBUG_HD
    printl("position=%d\n",position);
#endif
    assert((position>>SECTOR_SIZE_SHIFT)<(1<<31),"");
    assert(position%SECTOR_SIZE==0,"hd readwrite start position must be the multiple of SECTOR_SIZE");//读取的起始位置必须在扇区的起始位置

    HD_COMMAND hd_command;
    u32 base=get_part_info(&hd_info[hd_index],hd_part_index)->base;
    u32 sector_index=base+(u32)(position>>SECTOR_SIZE_SHIFT);
    int sector_length=(message->length+SECTOR_SIZE-1)/SECTOR_SIZE;
    int cmd=(message->type==INFO_FS_READ)?ATA_READ:ATA_WRITE;
    set_command(&hd_command,hd_index,0,0,sector_length,sector_index,cmd);
    hd_command_out(&hd_command);

    int bytes_left=message->length;
#ifdef DEBUG_HD
    printl("sector_index=%d sector_length=%d bytes_left=%d\n",sector_index,sector_length,bytes_left);
#endif
    void *la=(void *)va2la(message->source_pid,message->arg_pointer);
#ifdef DEBUG_HD
    printl("source_pid=%d la[0]=%d\n",message->source_pid,*(int*)la);
#endif
//此处需要注意:while(1),while(-1)都会执行循环体,只有while(0)时才跳出循环体
    while(bytes_left>0){
        int bytes=min(SECTOR_SIZE,bytes_left);
        if(message->type==INFO_FS_READ){
            interrupt_wait();
            port_read(REG_P_DATA,hdbuf,SECTOR_SIZE);
            memcpy(la,(void *)va2la(TASK_HD,hdbuf),bytes);
        }else{
            if(!wait_for(STATUS_DRQ_MASK,STATUS_DRQ,HD_TIME_OUT))
                panic("hd writing error!\n");
            /* printl("bytes=%d",bytes); */
            port_write(REG_P_DATA,la,bytes);
            /* printl("test1"); */
            interrupt_wait();
            /* printl("test2"); */
        }
        bytes_left-=bytes;
        la+=bytes;
        /* printl("(bytes_left>0)=%d\n",bytes_left>0); */
    }
#ifdef DEBUG_HD
    printl("hd_rdwt ok!\n");
#endif
}
예제 #6
0
파일: hd.c 프로젝트: Zach41/OS
PRIVATE void hd_ioctl(MESSAGE* p_msg) {
    int device = p_msg -> DEVICE;
    int drive  = DRV_OF_DEV(device);

    HD_INFO* hdi = &hd_info[drive];

    if (p_msg -> REQUEST == DIOCTL_GET_GEO) {
	void* dst = va2la(p_msg -> PROC_NR, p_msg -> BUF);
	void* src = va2la(TASK_HD, device < MAX_PRIM ? &hdi->primary[drive] : &hdi->logical[(device - MINOR_hd1a) % NR_SUB_PER_DRIVE]);
	memcpy(dst, src, sizeof(PART_ENT));
    } else {
	spin("HD No IO CTL");
    }
}
예제 #7
0
파일: disklog.c 프로젝트: wwssllabcd/myOS
/**
 * Perform syslog() system call .
 *
 * @return 
 *****************************************************************************/
PUBLIC int do_disklog()
{
	char buf[STR_DEFAULT_LEN];

	/* get parameters from the message */
	int str_len = fs_msg.CNT;	/* length of filename */
	int src = fs_msg.source;	/* caller proc nr. */
	assert(str_len < STR_DEFAULT_LEN);
	phys_copy((void*)va2la(TASK_FS, buf),    /* to   */
		  (void*)va2la(src, fs_msg.BUF), /* from */
		  str_len);
	buf[str_len] = 0;	/* terminate the string */

	return disklog(buf);
}
예제 #8
0
파일: misc.c 프로젝트: speedjiu/tiny_os
/*****************************************************************************
 *                                do_stat
 *************************************************************************//**
 * Perform the stat() syscall.
 * 
 * @return  On success, zero is returned. On error, -1 is returned.
 *****************************************************************************/
PUBLIC int do_stat()
{
	char pathname[MAX_PATH]; /* parameter from the caller */
	char filename[MAX_PATH]; /* directory has been stipped */

	/* get parameters from the message */
	int name_len = fs_msg.NAME_LEN;	/* length of filename */
	int src = fs_msg.source;	/* caller proc nr. */
	assert(name_len < MAX_PATH);
	phys_copy((void*)va2la(TASK_FS, pathname),    /* to   */
		  (void*)va2la(src, fs_msg.PATHNAME), /* from */
		  name_len);
	pathname[name_len] = 0;	/* terminate the string */

	int inode_nr = search_file(pathname);
	if (inode_nr == INVALID_INODE) {	/* file not found */
		printl("{FS} FS::do_stat():: search_file() returns "
		       "invalid inode: %s\n", pathname);
		return -1;
	}

	struct inode * pin = 0;

	struct inode * dir_inode;
	if (strip_path(filename, pathname, &dir_inode) != 0) {
		/* theoretically never fail here
		 * (it would have failed earlier when
		 *  search_file() was called)
		 */
		assert(0);
	}
	pin = get_inode(dir_inode->i_dev, inode_nr);

	struct stat s;		/* the thing requested */
	s.st_dev = pin->i_dev;
	s.st_ino = pin->i_num;
	s.st_mode= pin->i_mode;
	s.st_rdev= is_special(pin->i_mode) ? pin->i_start_sect : NO_DEV;
	s.st_size= pin->i_size;

	put_inode(pin);

	phys_copy((void*)va2la(src, fs_msg.BUF), /* to   */
		  (void*)va2la(TASK_FS, &s),	 /* from */
		  sizeof(struct stat));

	return 0;
}
예제 #9
0
PUBLIC int sys_sendrec(PROCESS *p, int function, int src_dest, MESSAGE *m)
{
    assert(k_reenter == 0);
    assert((src_dest >= 0 && src_dest < NR_TASKS + NR_PROCS) ||
           src_dest == ANY ||
           src_dest == INTERRUPT);

    int ret = 0;
    int caller = proc2pid(p);
    MESSAGE *mla = (MESSAGE *)va2la(caller, m);
    mla->source = caller;

    assert(mla->source != src_dest);

    if (function == SEND) {
        ret = msg_send(p, src_dest, m);
    }
    else if (function == RECEIVE) {
        ret = msg_receive(p, src_dest, m);
    }
    else {
        panic("{sys_sendrec} invalid function: "
              "%d (SEND:%d, RECEIVE:%d).", function, SEND, RECEIVE);
    }

    return ret;
}
예제 #10
0
파일: proc.c 프로젝트: liangbizhi/bzOS
/**************************************************************************************************
 * 					sys_sendrec
 **************************************************************************************************
 * <Ring 0> The core routine of system call 'sendrec'.
 * 
 * @param function	SEND, RECEIVE, BOTH
 * @param src_dest	To / From whom the message is transferred
 * @param msg		Pointer to the MESSAGE struct
 * @param proc		The caller process
 *
 * @return		0 if success
 *************************************************************************************************/
PUBLIC int sys_sendrec(int function, int src_dest, MESSAGE* msg, PROCESS* proc){
	assert(k_reenter == 0);			/* make sure we are not in ring0 */
	assert((src_dest >= 0 && src_dest < NR_TASKS + NR_PROCS) ||
		src_dest == ANY ||
		src_dest == INTERRUPT);

	int ret		= 0;
	int caller	= proc2pid(proc);
	MESSAGE* mla	= (MESSAGE*) va2la(caller, msg);
	mla->source	= caller;		/* from caller */

	assert(mla->source != src_dest);

	/**
	 * Actually we have the third message type: BOTH. However, it is not allowed to be passed
	 * to the kernel directly. Kernel doesn't know it at all. It is transformed into a SEND
	 * followed by RECEIVE by 'send_recv()'.
	 */
	if(function == SEND){
		ret = msg_send(proc, src_dest, msg);
		if(ret != 0){
			return ret;
		}
	}else if(function == RECEIVE){
		ret = msg_receive(proc, src_dest, msg);
		if(ret != 0){
			return ret;
		}
	}else{
		panic("{sys_sendrec} invalid function: %d (SEND: %d, RECEIVE: %d).", function, SEND, RECEIVE);
	}
	return 0;
}
예제 #11
0
파일: hd.c 프로젝트: yankaifyyy/Owindy-S
PRIVATE void hd_ioctl(MESSAGE *p)
{
    int device = p->DEVICE;
    int drive = DRV_OF_DEV(device);

    struct hd_info *hdi = &hdinfo[drive];

    if (p->REQUEST == DIOCTL_GET_GEO) {
        void *dst = va2la(p->PROC_NR, p->BUF);
        void *src = va2la(TASK_HD,
                device < MAX_PRIM ?
                &hdi->primary[device] :
                &hdi->logical[(device - MINOR_hd1a) % NR_SUB_PER_DRIVE]);
        phys_copy(dst, src, sizeof (struct part_info));
    } else {
        kprintf("[KERNEL ERROR]error ioctl cmd\n");
    }
}
예제 #12
0
파일: hd.c 프로젝트: yankaifyyy/Owindy-S
PRIVAATE void hd_rdwt(MESSAGE *p)
{
    int drive = DRV_OF_DEV(p->DEVICE);
    
    u64_t pos = p->POSITION;
    
    u32_t sect_nr = (u32_t)(pos >> SECTOR_SIZE_SHIFT);

    int logidx = (p->DEVICE - MINOR_HD1a) % NR_SUB_PER_DRIVE;
    sect_nr += p->DEVICE < MAX_PRIM ?
        hd_info[drive].primary[p->DEVICE].base :
        hd_info[drive].logical[logidx].base;

    struct hd_cmd cmd;
    cmd.features = 0;
    cmd.count = (p->CNT + SECTOR_SIZE - 1) / SECTOR_SIZE;
    cmd.lba_low = sect_nr & 0xff;
    cmd.lba_mid = (sect_nr >> 8) & 0xff;
    cmd.lba_high = (sect_nr >> 16) & 0xff;
    cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xf);
    cmd.command = (p->type == DEV_READ) ? ATA_READ : ATA_WRITE;
    hd_cmd_out(&cmd);

    int bytes_left = p->CNT;
    void *la = (void*)va2la(p->PROC_NR, p->BUF);

    while (bytes_left) {
        int bytes = min(SECTOR_SIZE, bytes_left);
        if (p->type == DEV_READ) {
            interrupt_wait();
            port_read(REG_DATA, hdbuf, SECTOR_SIZE);
            phys_copy(la, (void*)va2la(TASK_HD, hdbuf), bytes);
        } else {
            if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT)) {
                kprintf("[KERNEL ERROR]hd writing error.\n");
                break;
            }
            port_write(REG_DATA, la, bytes);
            interrupt_wait();
        }
        bytes_left -= SECTOR_SIZE;
        la += SECTOR_SIZE;
    }
}
예제 #13
0
파일: tty.c 프로젝트: wsxiaoys/OS-Practice
/**
 * Invoked when task TTY receives DEV_WRITE message.
 * 
 * @param tty  To which TTY the calller proc is bound.
 * @param msg  The MESSAGE.
 *****************************************************************************/
PRIVATE void tty_do_write(TTY* tty, MESSAGE* msg)
{
	char buf[TTY_OUT_BUF_LEN];
	char * p = (char*)va2la(msg->PROC_NR, msg->BUF);
	int i = msg->CNT;
	int j;

	while (i) {
		int bytes = min(TTY_OUT_BUF_LEN, i);
		phys_copy(va2la(TASK_TTY, buf), (void*)p, bytes);
		for (j = 0; j < bytes; j++)
			out_char(tty->console, buf[j]);
		i -= bytes;
		p += bytes;
	}

	msg->type = SYSCALL_RET;
	send_recv(SEND, msg->source, msg);
}
예제 #14
0
파일: do_stat.c 프로젝트: Zach41/OS
PUBLIC int do_stat() {
    char pathname[MAX_PATH];
    char filename[MAX_PATH];

    int name_len = fs_msg.NAME_LEN;
    int src      = fs_msg.source;
    
    memcpy((void*)va2la(TASK_FS, pathname),
	   (void*)va2la(src, fs_msg.PATHNAME),
	   name_len);
    pathname[name_len] = 0;

    int inode_nr = search_file(pathname);

    if (inode_nr == INVALID_INODE) {
	printl("FS::do_stat() failed, search file %s return INVALID INODE.\n", pathname);
	return -1;
    }

    struct inode* pin = 0;
    struct inode* dir_inode = 0;
    if(strip_path(filename, pathname, &dir_inode) != 0) {
	assert(0);
    }

    pin = get_inode(dir_inode -> i_dev, inode_nr);

    struct stat s;

    s.st_dev  = pin -> i_dev;
    s.st_ino  = pin -> i_num;
    s.st_mode = pin -> i_mode;
    s.st_rdev = pin -> i_mode == I_CHAR_SPECIAL ? pin -> i_start_sect : NO_DEV;
    s.st_size = pin -> i_size;

    put_inode(pin);

    memcpy((void*)va2la(src, fs_msg.BUF),
	   (void*)va2la(TASK_FS, &s),
	   sizeof(struct stat));

    return 0;
}
예제 #15
0
파일: hd.c 프로젝트: cosail/lwos
/*
 * <ring 1> this routine handles the DEV_IOCTL messge.
 *
 * @param msg - message.
 */
static void hd_ioctl(MESSAGE *msg)
{
	int device = msg->DEVICE;
	int drive = DRV_OF_DEV(device);

	struct hd_info *hdi = &hd_info[drive];

	if (msg->REQUEST == DIOCTL_GET_GEO)
	{
		void *dst = va2la(msg->PROC_NR, msg->BUF);
		void *src = va2la(TASK_HD, device < MAX_PRIM ?
			&hdi->primary[device] :
			&hdi->logical[(device - MINOR_hd1a) % NR_SUB_PER_DRIVE]);
		phys_copy(dst, src, sizeof(struct part_info));
	}
	else
	{
		assert(0);
	}
}
예제 #16
0
파일: hd.c 프로젝트: Zach41/OS
PRIVATE void hd_rdwt(MESSAGE* p_msg) {
    int drive = DRV_OF_DEV(p_msg -> DEVICE);
    u64 pos = p_msg -> POSITION;

    assert((pos & 0x1FF) == 0);	/* 只允许从扇区边界开始读 */

    u32 sect_nr = (u32)(pos >> SECTOR_SIZE_SHIFT);
    int logidx  = (p_msg -> DEVICE - MINOR_hd1a) % NR_SUB_PER_DRIVE;
    sect_nr    += p_msg -> DEVICE < MAX_PRIM ? hd_info[drive].primary[p_msg -> DEVICE].base : hd_info[drive].logical[logidx].base;
    
    HD_CMD cmd;
    cmd.features = 0;
    cmd.count    = (p_msg -> CNT + SECTOR_SIZE - 1) / SECTOR_SIZE;
    cmd.lba_low  = sect_nr & 0xFF;
    cmd.lba_mid  = (sect_nr >> 8) & 0xFF;
    cmd.lba_high = (sect_nr >> 16) & 0xFF;
    cmd.device   = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xF);
    cmd.command  = (p_msg -> type == DEV_READ) ? ATA_READ : ATA_WRITE;
    hd_cmd_out(&cmd);

    int bytes_left = p_msg -> CNT;
    void* la = (void*)va2la(p_msg -> PROC_NR, p_msg -> BUF);

    while (bytes_left > 0) {
	int bytes = min(bytes_left, SECTOR_SIZE);
	if (p_msg -> type == DEV_READ) {
	    /* 一次中断一个扇区 */
	    interrupt_wait();
	    port_read(REG_DATA, hdbuf, SECTOR_SIZE);
	    memcpy(la, (void*)va2la(TASK_HD, hdbuf), bytes);
	} else {
	    if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT))
		panic("HD writing error");
	    port_write(REG_DATA, la, bytes);
	    interrupt_wait();
	}
	la += bytes;
	bytes_left -= bytes;
    }
}
예제 #17
0
파일: tty.c 프로젝트: Shelro/TJinix
/**
 * Invoked when task TTY receives DEV_READ message.
 *
 * @note The routine will return immediately after setting some members of
 * TTY struct, telling FS to suspend the proc who wants to read. The real
 * transfer (tty buffer -> proc buffer) is not done here.
 * 
 * @param tty  From which TTY the caller proc wants to read.
 * @param msg  The MESSAGE just received.
 *****************************************************************************/
PRIVATE void tty_do_read(TTY* tty, MESSAGE* msg)
{
	/* tell the tty: */
	tty->tty_caller   = msg->source;  /* who called, usually FS */
	tty->tty_procnr   = msg->PROC_NR; /* who wants the chars */
	tty->tty_req_buf  = va2la(tty->tty_procnr,
				  msg->BUF);/* where the chars should be put */
	tty->tty_left_cnt = msg->CNT; /* how many chars are requested */
	tty->tty_trans_cnt= 0; /* how many chars have been transferred */

	msg->type = SUSPEND_PROC;
	send_recv(SEND, tty->tty_caller, msg);
}
예제 #18
0
/**************************************************************
 *               do_stat
 **************************************************************
	@function:get the information of a pathname
		The information we need for stat hided in the inode. So we just need to get the info of inode of pathname.
	@input:
	@return:0 if sucess
**************************************************************/
int hykdo_stat()
{
    char filename[MAX_FILENAME_LEN];
    char pathname[MAX_PATH_LEN];
    int pathname_len = fs_msg.NAME_LEN;
    int src = fs_msg.source;
//	pathname = fs_msg.PATHNAME; /*no!!! you can not do this directly! For they are not in the same address space*/
    phys_copy( (void *)va2la(TASK_FS, pathname),\
               (void *)va2la(src, fs_msg.PATHNAME),\
               fs_msg.NAME_LEN);
    pathname[pathname_len] = 0;

    int inode_nr_path = search_file(pathname);
    if(inode_nr_path == INVALID_INODE) {
        printl("[FS]:stat faild becase of invalid inode\n");
        return -1;
    }
    struct inode *dir_inode;
    if(strip_path(filename, pathname, &dir_inode)!=0) {
        assert(0);
    }
    struct inode *file_inode=get_inode(dir_inode->i_dev, inode_nr_path);

    struct stat s;
    s.dev = file_inode->i_dev;
    s.size = file_inode->i_size;
    s.mode = file_inode->i_mode;
    s.ino = file_inode->i_num;
    s.rdev = is_special(file_inode->i_mode) ? file_inode->i_start_sect: NO_DEV;

    put_inode(file_inode);

    phys_copy( (void *)va2la(src, fs_msg.BUF),\
               (void *)va2la(TASK_FS, &stat),\
               sizeof(struct stat));
    printl("fs_msg.buf.size:%x", ((struct stat *)va2la(src, fs_msg.BUF))->size);
    return 0;
}
예제 #19
0
파일: hd.c 프로젝트: 565407548/micro_os
static void hd_ioctl(MESSAGE *message){
    int hd_index=HD_INDEX(message->device);
    int hd_part_index=HD_PART_INDEX(message->device);

    struct s_hd_info *hdi=&hd_info[hd_index];

#ifdef DEBUG_HD
    printl("hd_index=%d hd_part_index=%d\n",hd_index,hd_part_index);
#endif

    if(message->subtype==DIOCTL_GET_PART_INFO){
        void *dest=va2la(message->source_pid,message->arg_pointer);
        /* void *src=va2la(TASK_HD, */
        /*     hd_part_index<=HD_PART_PRIM_COUNT? */
        /*                 &hdi->primary[hd_part_index]: */
        /*                 &hdi->logical[hd_part_index-HD_PART_LOGICAL_MIN]); */
        void *src=va2la(TASK_HD,get_part_info(&hdi[hd_index],hd_part_index));
        
        memcpy(dest,src,sizeof(struct s_hd_part_info));
    }else{
        assert(FALSE,"unknown message subtype in hd_ioctl");
    }
}
예제 #20
0
파일: tty.c 프로젝트: RCmerci/xos
static int do_read(MESSAGE * m)
{
  TTY * tty_p = &(tty_table[m->tty_read_TTY_NR]);
  int nbytes  = ((MESSAGE*)(m->tty_read_REQUEST_M))->read_NBYTES;
  u8 * buf    = va2la(((MESSAGE*)(m->tty_read_REQUEST_M))->sender_pid,
		      (u8*)((MESSAGE*)(m->tty_read_REQUEST_M))->read_BUF);
  int curr_rst = ((MESSAGE*)(m->tty_read_REQUEST_M))->read_RST;
  char * last_read_p = (char*)(m->LAST_READ_POS);
  
  char c;
  if (curr_rst == 0) {
    last_read_p = tty_p->in_tail_p;
  }
  while (last_read_p != tty_p->in_head_p) {
    c = *last_read_p;
    /* if (curr_rst == nbytes && c != '\n') { /\* 已经足够,但是本次char不是\n *\/ */
    /*   last_read_p++; */
    /*   if (last_read_p == tty_p->tty_in_cache + TTY_CHAR_CACHE_SIZE) { */
    /* 	last_read_p = tty_p->tty_in_cache; */
    /*   } */
    /*   m->LAST_READ_POS = (u32)last_read_p; */
    /*   return 0; */
    /* } */
    /* if (curr_rst == nbytes && c == '\n') { /\* 已经足够而且本次char==\n *\/ */
    /*   return 1; */
    /* } */
    buf[curr_rst] = c;
    tty_p->in_tail_p ++ ;
    if (tty_p->in_tail_p == tty_p->tty_in_cache + TTY_CHAR_CACHE_SIZE) {
      tty_p->in_tail_p = tty_p->tty_in_cache;
    }
    last_read_p = tty_p->in_tail_p;
    tty_p->in_count -- ;
    curr_rst ++ ;
    ((MESSAGE*)(m->tty_read_REQUEST_M))->read_RST ++ ;
    
    if (curr_rst == nbytes) {	/* 加上本次char刚好足够nbytes */
      //      if (c == '\n') {		/* 本次char ==\n, 直接成功返回 */
      ((MESSAGE*)(m->tty_read_REQUEST_M))->read_RST = nbytes;
      return 1;
	//      }
    }
  }
  m->LAST_READ_POS = (u32)last_read_p;
  return 0;
}
예제 #21
0
파일: tty.c 프로젝트: monomaniar/prettyos
/*
   int sys_write(char *buf,int len,struct task_struct *p_proc)
   {
   tty_write(&tty_table[p_proc->nr_tty],buf,len);
   return 0;
   }
   */
int sys_printx(char *s,int len,struct task_struct *p_proc)
{
    const char *p;
    char ch;
    char reenter_err[] = "? k_reenter is incorrect for unknown reason\n";

    if(k_reenter == 0)	//用户态下
    {
        p = (char *)va2la(proc2pid(p_proc),s);
    }
    else if(k_reenter > 0) //内核态
    {
        p =s;		
    }
    else
    {
        p = reenter_err;
    }

    ch = *p;
    if((ch == MAG_CH_PANIC) || (ch == MAG_CH_ASSERT && current < &proc_table[NR_SYSTEM_PROCS]))
    {
        disable_int(); //关中断
        char *v = (char *)V_MEM_BASE;
        const char *c = p + 1; //skip magic char
        while( v < ((char *)(V_MEM_BASE + V_MEM_SIZE)) && *c)
        {
            *v++ = *c++;
            *v++ = RED_COLOR; 
        }

        //halt processor until an enabled interrupt
        __asm__ __volatile__ ("hlt");
    }
    else
    {

        while((ch = *p++) != 0)	
        {
            out_char(tty_table[p_proc->nr_tty].p_console,ch);
        }
    }

    return 0;
}
예제 #22
0
PUBLIC int sys_sendrec(int function, int src_dest, Message *p_msg, Process *p_proc)
{
	 assert(k_reenter == 0);
	 assert((src_dest >= 0 && src_dest < NR_TASKS + NR_PROCS) ||
			src_dest == ANY ||
			src_dest == INTERRUPT);

	 int ret = 0;
	 int caller = proc2pid(p_proc);
	 Message *mla = (Message *)va2la(caller, p_msg);
	 mla->source = caller;

	 assert(mla->source != src_dest);

	 /* Actually we have the third message type: BOTH. However, it is not
	 * allowed to be passed to the kernel directly. Kernel doesn't know
	 * it at all. It is transformed into a SEDN followed by a RECEIVE
	 * by 'send_recv()'.
	 */
	 if(function == SEND)
	 {
		  ret = msg_send(p_proc, src_dest, p_msg);
		  if(ret != 0)
		  {
			   return ret;
		  }
	 }
	 else if(function == RECEIVE)
	 {
		  ret = msg_receive(p_proc, src_dest, p_msg);
		  if(ret != 0)
		  {
			   return ret;
		  }
	 }
	 else
	 {
		  panic("{sys_sendrec} invalid function: "
				"%d (SEND: %d, RECEIVE: %d).",
				function, SEND, RECEIVE);
	 }
	 return 0;
}
예제 #23
0
파일: tty.c 프로젝트: RCmerci/xos
static int do_write(MESSAGE * m)
{
  TTY * tty_p = &(tty_table[m->tty_write_TTY_NR]);
  int nbytes  = ((MESSAGE*)(m->tty_write_REQUEST_M))->write_NBYTES;
  u8 * buf    = va2la(((MESSAGE*)(m->tty_write_REQUEST_M))->sender_pid,
		      (u8*)((MESSAGE*)(m->tty_write_REQUEST_M))->write_BUF);
  int curr_rst = ((MESSAGE*)(m->tty_write_REQUEST_M))->write_RST;
  char * last_write_p = (char*)(m->LAST_WRITE_POS);
  
  if(nbytes == 0) {
    ((MESSAGE*)(m->tty_write_REQUEST_M))->write_RST = 0;
    return 1;
  }
  
  if (curr_rst == 0) last_write_p = tty_p->out_head_p;
  
  while(1) {
    *last_write_p = buf[curr_rst];
    last_write_p ++ ;
    if (last_write_p == tty_p->tty_out_cache + TTY_CHAR_CACHE_SIZE)
      last_write_p = tty_p->tty_out_cache;
    curr_rst ++ ;
    tty_p->out_head_p ++ ;
    if (tty_p->out_head_p == tty_p->tty_out_cache + TTY_CHAR_CACHE_SIZE)
      tty_p->out_head_p = tty_p->tty_out_cache;
    if (tty_p->out_tail_p == tty_p->out_head_p) {
      assert(tty_p->out_count == TTY_CHAR_CACHE_SIZE);
      tty_p->out_tail_p ++ ;
      if (tty_p->out_tail_p == tty_p->tty_out_cache + TTY_CHAR_CACHE_SIZE)
	tty_p->out_tail_p = tty_p->tty_out_cache;
    } else {
      tty_p->out_count ++ ;
    }
    if (curr_rst == nbytes) {
      ((MESSAGE*)(m->tty_write_REQUEST_M))->write_RST = curr_rst;
      return 1;
    }
  }
  m->LAST_WRITE_POS = last_write_p;
  return 0;
}
예제 #24
0
파일: tty.c 프로젝트: Shelro/TJinix
/**
 * Echo the char just pressed and transfer it to the waiting process.
 * 
 * @param tty   Ptr to a TTY struct.
 *****************************************************************************/
PRIVATE void tty_dev_write(TTY* tty)
{
	while (tty->ibuf_cnt) {
		char ch = *(tty->ibuf_tail);
		tty->ibuf_tail++;
		if (tty->ibuf_tail == tty->ibuf + TTY_IN_BYTES)
			tty->ibuf_tail = tty->ibuf;
		tty->ibuf_cnt--;

		if (tty->tty_left_cnt) {
			if (ch >= ' ' && ch <= '~') { /* printable */
				out_char(tty->console, ch);

				assert(tty->tty_req_buf);
				void * p = tty->tty_req_buf +
					   tty->tty_trans_cnt;
				phys_copy(p, (void *)va2la(TASK_TTY, &ch), 1);

				tty->tty_trans_cnt++;
				tty->tty_left_cnt--;
			}
			else if (ch == '\b' && tty->tty_trans_cnt) {
				out_char(tty->console, ch);
				tty->tty_trans_cnt--;
				tty->tty_left_cnt++;
			}

			if (ch == '\n' || tty->tty_left_cnt == 0) {
				out_char(tty->console, '\n');

				assert(tty->tty_procnr != NO_TASK);
				MESSAGE msg;
				msg.type = RESUME_PROC;
				msg.PROC_NR = tty->tty_procnr;
				msg.CNT = tty->tty_trans_cnt;
				send_recv(SEND, tty->tty_caller, &msg);
				tty->tty_left_cnt = 0;
			}
		}
	}
}
예제 #25
0
파일: proc.c 프로젝트: smilingjames/Sinix
/**
 * <Ring 0> Try to get a message from the src proc. If src is blocked sending
 * the message, copy the message from it and unblock src. Otherwise the caller
 * will be blocked.
 * 
 * @param current The caller, the proc who wanna receive.
 * @param src     From whom the message will be received.
 * @param m       The message ptr to accept the message.
 * 
 * @return  Zero if success.
 *****************************************************************************/
PRIVATE int msg_receive(struct proc* current, int src, MESSAGE* m)
{
	struct proc* p_who_wanna_recv = current; /**
						  * This name is a little bit
						  * wierd, but it makes me
						  * think clearly, so I keep
						  * it.
						  */
	struct proc* p_from = 0; /* from which the message will be fetched */
	struct proc* prev = 0;
	int copyok = 0;

	assert(proc2pid(p_who_wanna_recv) != src);

	if ((p_who_wanna_recv->has_int_msg) &&
	    ((src == ANY) || (src == INTERRUPT))) {
		/* There is an interrupt needs p_who_wanna_recv's handling and
		 * p_who_wanna_recv is ready to handle it.
		 */

		MESSAGE msg;
		reset_msg(&msg);
		msg.source = INTERRUPT;
		msg.type = HARD_INT;
		assert(m);
		phys_copy(va2la(proc2pid(p_who_wanna_recv), m), &msg,
			  sizeof(MESSAGE));

		p_who_wanna_recv->has_int_msg = 0;

		assert(p_who_wanna_recv->p_flags == 0);
		assert(p_who_wanna_recv->p_msg == 0);
		assert(p_who_wanna_recv->p_sendto == NO_TASK);
		assert(p_who_wanna_recv->has_int_msg == 0);

		return 0;
	}


	/* Arrives here if no interrupt for p_who_wanna_recv. */
	if (src == ANY) {
		/* p_who_wanna_recv is ready to receive messages from
		 * ANY proc, we'll check the sending queue and pick the
		 * first proc in it.
		 */
		if (p_who_wanna_recv->q_sending) {
			p_from = p_who_wanna_recv->q_sending;
			copyok = 1;

			assert(p_who_wanna_recv->p_flags == 0);
			assert(p_who_wanna_recv->p_msg == 0);
			assert(p_who_wanna_recv->p_recvfrom == NO_TASK);
			assert(p_who_wanna_recv->p_sendto == NO_TASK);
			assert(p_who_wanna_recv->q_sending != 0);
			assert(p_from->p_flags == SENDING);
			assert(p_from->p_msg != 0);
			assert(p_from->p_recvfrom == NO_TASK);
			assert(p_from->p_sendto == proc2pid(p_who_wanna_recv));
		}
	}
	else {
		/* p_who_wanna_recv wants to receive a message from
		 * a certain proc: src.
		 */
		p_from = &proc_table[src];

		if ((p_from->p_flags & SENDING) &&
		    (p_from->p_sendto == proc2pid(p_who_wanna_recv))) {
			/* Perfect, src is sending a message to
			 * p_who_wanna_recv.
			 */
			copyok = 1;

			struct proc* p = p_who_wanna_recv->q_sending;
			assert(p); /* p_from must have been appended to the
				    * queue, so the queue must not be NULL
				    */
			while (p) {
				assert(p_from->p_flags & SENDING);
				if (proc2pid(p) == src) { /* if p is the one */
					p_from = p;
					break;
				}
				prev = p;
				p = p->next_sending;
			}

			assert(p_who_wanna_recv->p_flags == 0);
			assert(p_who_wanna_recv->p_msg == 0);
			assert(p_who_wanna_recv->p_recvfrom == NO_TASK);
			assert(p_who_wanna_recv->p_sendto == NO_TASK);
			assert(p_who_wanna_recv->q_sending != 0);
			assert(p_from->p_flags == SENDING);
			assert(p_from->p_msg != 0);
			assert(p_from->p_recvfrom == NO_TASK);
			assert(p_from->p_sendto == proc2pid(p_who_wanna_recv));
		}
	}

	if (copyok) {
		/* It's determined from which proc the message will
		 * be copied. Note that this proc must have been
		 * waiting for this moment in the queue, so we should
		 * remove it from the queue.
		 */
		if (p_from == p_who_wanna_recv->q_sending) { /* the 1st one */
			assert(prev == 0);
			p_who_wanna_recv->q_sending = p_from->next_sending;
			p_from->next_sending = 0;
		}
		else {
			assert(prev);
			prev->next_sending = p_from->next_sending;
			p_from->next_sending = 0;
		}

		assert(m);
		assert(p_from->p_msg);
		/* copy the message */
		phys_copy(va2la(proc2pid(p_who_wanna_recv), m),
			  va2la(proc2pid(p_from), p_from->p_msg),
			  sizeof(MESSAGE));

		p_from->p_msg = 0;
		p_from->p_sendto = NO_TASK;
		p_from->p_flags &= ~SENDING;
		unblock(p_from);
	}
	else {  /* nobody's sending any msg */
		/* Set p_flags so that p_who_wanna_recv will not
		 * be scheduled until it is unblocked.
		 */
		p_who_wanna_recv->p_flags |= RECEIVING;

		p_who_wanna_recv->p_msg = m;

		if (src == ANY)
			p_who_wanna_recv->p_recvfrom = ANY;
		else
			p_who_wanna_recv->p_recvfrom = proc2pid(p_from);

		block(p_who_wanna_recv);

		assert(p_who_wanna_recv->p_flags == RECEIVING);
		assert(p_who_wanna_recv->p_msg != 0);
		assert(p_who_wanna_recv->p_recvfrom != NO_TASK);
		assert(p_who_wanna_recv->p_sendto == NO_TASK);
		assert(p_who_wanna_recv->has_int_msg == 0);
	}

	return 0;
}
예제 #26
0
파일: proc.c 프로젝트: smilingjames/Sinix
/**
 * <Ring 0> Send a message to the dest proc. If dest is blocked waiting for
 * the message, copy the message to it and unblock dest. Otherwise the caller
 * will be blocked and appended to the dest's sending queue.
 * 
 * @param current  The caller, the sender.
 * @param dest     To whom the message is sent.
 * @param m        The message.
 * 
 * @return Zero if success.
 *****************************************************************************/
PRIVATE int msg_send(struct proc* current, int dest, MESSAGE* m)
{
	struct proc* sender = current;
	struct proc* p_dest = proc_table + dest; /* proc dest */

	assert(proc2pid(sender) != dest);

	/* check for deadlock here */
	if (deadlock(proc2pid(sender), dest)) {
		panic(">>DEADLOCK<< %s->%s", sender->name, p_dest->name);
	}

	if ((p_dest->p_flags & RECEIVING) && /* dest is waiting for the msg */
	    (p_dest->p_recvfrom == proc2pid(sender) ||
	     p_dest->p_recvfrom == ANY)) {
		assert(p_dest->p_msg);
		assert(m);

		phys_copy(va2la(dest, p_dest->p_msg),
			  va2la(proc2pid(sender), m),
			  sizeof(MESSAGE));
		p_dest->p_msg = 0;
		p_dest->p_flags &= ~RECEIVING; /* dest has received the msg */
		p_dest->p_recvfrom = NO_TASK;
		unblock(p_dest);

		assert(p_dest->p_flags == 0);
		assert(p_dest->p_msg == 0);
		assert(p_dest->p_recvfrom == NO_TASK);
		assert(p_dest->p_sendto == NO_TASK);
		assert(sender->p_flags == 0);
		assert(sender->p_msg == 0);
		assert(sender->p_recvfrom == NO_TASK);
		assert(sender->p_sendto == NO_TASK);
	}
	else { /* dest is not waiting for the msg */
		sender->p_flags |= SENDING;
		assert(sender->p_flags == SENDING);
		sender->p_sendto = dest;
		sender->p_msg = m;

		/* append to the sending queue */
		struct proc * p;
		if (p_dest->q_sending) {
			p = p_dest->q_sending;
			while (p->next_sending)
				p = p->next_sending;
			p->next_sending = sender;
		}
		else {
			p_dest->q_sending = sender;
		}
		sender->next_sending = 0;

		block(sender);

		assert(sender->p_flags == SENDING);
		assert(sender->p_msg != 0);
		assert(sender->p_recvfrom == NO_TASK);
		assert(sender->p_sendto == dest);
	}

	return 0;
}
예제 #27
0
파일: tty.c 프로젝트: chenghuaijun/Orange
/*======================================================================*
                              sys_write
*======================================================================*/
PUBLIC int sys_printx(int _unused1, int _unused2, char* s, struct proc* p_proc)
{
	const char * p;
	char ch;

	char reenter_err[] = "? k_reenter is incorrect for unknown reason";
	reenter_err[0] = MAG_CH_PANIC;

	/**
	 * @note Code in both Ring 0 and Ring 1~3 may invoke printx().
	 * If this happens in Ring 0, no linear-physical address mapping
	 * is needed.
	 *
	 * @attention The value of `k_reenter' is tricky here. When
	 *   -# printx() is called in Ring 0
	 *      - k_reenter > 0. When code in Ring 0 calls printx(),
	 *        an `interrupt re-enter' will occur (printx() generates
	 *        a software interrupt). Thus `k_reenter' will be increased
	 *        by `kernel.asm::save' and be greater than 0.
	 *   -# printx() is called in Ring 1~3
	 *      - k_reenter == 0.
	 */
	if (k_reenter == 0)  /* printx() called in Ring<1~3> */
		p = va2la(proc2pid(p_proc), s);
	else if (k_reenter > 0) /* printx() called in Ring<0> */
		p = s;
	else	/* this should NOT happen */
		p = reenter_err;

	/**
	 * @note if assertion fails in any TASK, the system will be halted;
	 * if it fails in a USER PROC, it'll return like any normal syscall
	 * does.
	 */
	if ((*p == MAG_CH_PANIC) ||
	    (*p == MAG_CH_ASSERT && p_proc_ready < &proc_table[NR_TASKS])) {
		disable_int();
		char * v = (char*)V_MEM_BASE;
		const char * q = p + 1; /* +1: skip the magic char */

		while (v < (char*)(V_MEM_BASE + V_MEM_SIZE)) {
			*v++ = *q++;
			*v++ = RED_CHAR;
			if (!*q) {
				while (((int)v - V_MEM_BASE) % (SCR_WIDTH * 16)) {
					/* *v++ = ' '; */
					v++;
					*v++ = GRAY_CHAR;
				}
				q = p + 1;
			}
		}

		__asm__ __volatile__("hlt");
	}

	while ((ch = *p++) != 0) {
		if (ch == MAG_CH_PANIC || ch == MAG_CH_ASSERT)
			continue; /* skip the magic char */

		out_char(tty_table[p_proc->nr_tty].p_console, ch);
	}

	return 0;
}
예제 #28
0
/**
 * Read/Write file and return byte count read/written.
 *
 * Sector map is not needed to update, since the sectors for the file have been
 * allocated and the bits are set when the file was created.
 * 
 * @return How many bytes have been read/written.
 *****************************************************************************/
PUBLIC int do_rdwt()
{
	int fd = fs_msg.FD;	/**< file descriptor. */
	void * buf = fs_msg.BUF;/**< r/w buffer */
	int len = fs_msg.CNT;	/**< r/w bytes */

	int src = fs_msg.source;		/* caller proc nr. */

	assert((pcaller->filp[fd] >= &f_desc_table[0]) &&
	       (pcaller->filp[fd] < &f_desc_table[NR_FILE_DESC]));

	if (!(pcaller->filp[fd]->fd_mode & O_RDWR))
		return -1;

	int pos = pcaller->filp[fd]->fd_pos;

	struct inode * pin = pcaller->filp[fd]->fd_inode;

	assert(pin >= &inode_table[0] && pin < &inode_table[NR_INODE]);

	int imode = pin->i_mode & I_TYPE_MASK;

	if (imode == I_CHAR_SPECIAL) {
		int t = fs_msg.type == READ ? DEV_READ : DEV_WRITE;
		fs_msg.type = t;

		int dev = pin->i_start_sect;
		assert(MAJOR(dev) == 4);

		fs_msg.DEVICE	= MINOR(dev);
		fs_msg.BUF	= buf;
		fs_msg.CNT	= len;
		fs_msg.PROC_NR	= src;
		assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER);
		send_recv(BOTH, dd_map[MAJOR(dev)].driver_nr, &fs_msg);
		assert(fs_msg.CNT == len);

		return fs_msg.CNT;
	}
	else {
		assert(pin->i_mode == I_REGULAR || pin->i_mode == I_DIRECTORY);
		assert((fs_msg.type == READ) || (fs_msg.type == WRITE));

		//讀寫不能超過檔案大小
		int pos_end;
		if (fs_msg.type == READ)
			pos_end = min(pos + len, pin->i_size);
		else		/* WRITE */
			pos_end = min(pos + len, pin->i_nr_sects * SECTOR_SIZE);


		//secNum的offset
		int off = pos % SECTOR_SIZE;

		//哪一個sector
		int rw_sect_min=pin->i_start_sect+(pos>>SECTOR_SIZE_SHIFT);

		//結束在那個sector
		int rw_sect_max=pin->i_start_sect+(pos_end>>SECTOR_SIZE_SHIFT);

		//扇區讀寫使用chunk為單位,如果一次buf傳的完的話,就使用rw_sect_max - rw_sect_min + 1
		int chunk = min(rw_sect_max - rw_sect_min + 1,
				FSBUF_SIZE >> SECTOR_SIZE_SHIFT);

		int bytes_rw = 0;
		int bytes_left = len;
		int i;

		for (i = rw_sect_min; i <= rw_sect_max; i += chunk) {
			/* read/write this amount of bytes every time */
			int bytes = min(bytes_left, chunk * SECTOR_SIZE - off);
			rw_sector(DEV_READ,
				  pin->i_dev,
				  i * SECTOR_SIZE,
				  chunk * SECTOR_SIZE,
				  TASK_FS,
				  fsbuf);

			if (fs_msg.type == READ) {
				phys_copy((void*)va2la(src, buf + bytes_rw),
					  (void*)va2la(TASK_FS, fsbuf + off),
					  bytes);
			}
			else {	/* WRITE */
				phys_copy((void*)va2la(TASK_FS, fsbuf + off),
					  (void*)va2la(src, buf + bytes_rw),
					  bytes);

				rw_sector(DEV_WRITE,
					  pin->i_dev,
					  i * SECTOR_SIZE,
					  chunk * SECTOR_SIZE,
					  TASK_FS,
					  fsbuf);
			}
			off = 0;
			bytes_rw += bytes;
			pcaller->filp[fd]->fd_pos += bytes;
			bytes_left -= bytes;
		}

		if (pcaller->filp[fd]->fd_pos > pin->i_size) {
			/* update inode::size */
			pin->i_size = pcaller->filp[fd]->fd_pos;

			/* write the updated i-node back to disk */
			sync_inode(pin);
		}

		return bytes_rw;
	}
}
예제 #29
0
PUBLIC int do_open()
{
    int i = 0;
    int fd = -1; // return value
    char pathname[MAX_PATH];

    int flags = fs_msg.FLAGS;
    int name_len = fs_msg.NAME_LEN;
    int src = fs_msg.source;

    assert(name_len < MAX_PATH);
    phys_copy(
        (void *)va2la(TASK_FS, pathname),
        (void *)va2la(src, fs_msg.PATHNAME),
        name_len
    );
    pathname[name_len] = 0;

    /* 先在调用者进程中查找空闲文件描述符 */
    for (i = 0; i < NR_FILES; i++)
        if (pcaller->filp[i] == 0) {
            fd = i;
            break;
        }
    if ((fd < 0) || (fd >= NR_FILES))
        panic("filp[] is full (PID:%d)", proc2pid(pcaller));

    /* 然后在 f_desc_table 中查找空闲位置 */
    for (i = 0; i < NR_FILE_DESC; i++)
        if (f_desc_table[i].fd_inode == 0)
            break;
    if (i >= NR_FILE_DESC)
        panic("f_desc_table[] is full (PID:%d)", proc2pid(pcaller));

    /* 在磁盘中查找文件 */
    int inode_nr = search_file(pathname);

    /* 准备创建或打开文件 */
    struct inode *pin = 0;
    if (flags & O_CREAT) {
        if (inode_nr) {
            printl("file exists.\n");
            return -1;
        }
        else { // 文件不存在且标志位 O_CREAT
            pin = creat_file(pathname, flags);
        }
    }
    else {
        assert(flags & O_RDWR);

        char filename[MAX_PATH];
        struct inode * dir_inode;
        if (strip_path(filename, pathname, &dir_inode) != 0)
            return -1;
        pin = get_inode(dir_inode->i_dev, inode_nr);
    }

    /* 关联文件描述符 */
    if (pin) {
        /* proc <- fd (connects proc with file_descriptor) */
        pcaller->filp[fd] = &f_desc_table[i];

        /* fd <- inode (connects file_descriptor with inode) */
        f_desc_table[i].fd_mode = flags;
        f_desc_table[i].fd_pos = 0;
        f_desc_table[i].fd_inode = pin;

        int imode = pin->i_mode & I_TYPE_MASK;
        if (imode == I_CHAR_SPECIAL) {
            MESSAGE driver_msg;

            driver_msg.type = DEV_OPEN;
            int dev = pin->i_start_sect;
            driver_msg.DEVICE = MINOR(dev);
            assert(MAJOR(dev) == 4);
            assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER);

            /* 如果是字符设备则交给该设备的驱动处理 */
            send_recv(BOTH, dd_map[MAJOR(dev)].driver_nr, &driver_msg);
        }
        else if (imode == I_DIRECTORY)
            assert(pin->i_num == ROOT_INODE);
        else
            assert(pin->i_mode == I_REGULAR);
    }
    else
        return -1; // open file failed

    return fd;
}
예제 #30
0
파일: open.c 프로젝트: kong123/STUDY
/**
 * Open a file and return the file descriptor.
 *
 * @return File descriptor if successful, otherwise a negative error code.
 *****************************************************************************/
PUBLIC int do_open()
{
    int fd = -1;		/* return value */

    char pathname[MAX_PATH];

    /* get parameters from the message */
    int flags = fs_msg.FLAGS;	/* access mode */
    int name_len = fs_msg.NAME_LEN;	/* length of filename */
    int src = fs_msg.source;	/* caller proc nr. */
    assert(name_len < MAX_PATH);
    phys_copy((void*)va2la(TASK_FS, pathname),
              (void*)va2la(src, fs_msg.PATHNAME),
              name_len);
    pathname[name_len] = 0;

    /* find a free slot in PROCESS::filp[] */
    int i;
    for (i = 0; i < NR_FILES; i++) {
        if (pcaller->filp[i] == 0) {
            fd = i;
            break;
        }
    }
    if ((fd < 0) || (fd >= NR_FILES))
        panic("filp[] is full (PID:%d)", proc2pid(pcaller));

    /* find a free slot in f_desc_table[] */
    for (i = 0; i < NR_FILE_DESC; i++)
        if (f_desc_table[i].fd_inode == 0)
            break;
    if (i >= NR_FILE_DESC)
        panic("f_desc_table[] is full (PID:%d)", proc2pid(pcaller));

    int inode_nr = search_file(pathname);

    struct inode * pin = 0;
    if (flags & O_CREAT) {
        if (inode_nr) {
            printl("file exists.\n");
            return -1;
        }
        else {
            pin = create_file(pathname, flags);
        }
    }
    else {
        assert(flags & O_RDWR);

        char filename[MAX_PATH];
        struct inode * dir_inode;
        if (strip_path(filename, pathname, &dir_inode) != 0)
            return -1;
        pin = get_inode(dir_inode->i_dev, inode_nr);
    }

    if (pin) {
        /* connects proc with file_descriptor */
        pcaller->filp[fd] = &f_desc_table[i];

        /* connects file_descriptor with inode */
        f_desc_table[i].fd_inode = pin;

        f_desc_table[i].fd_mode = flags;
        /* f_desc_table[i].fd_cnt = 1; */
        f_desc_table[i].fd_pos = 0;

        int imode = pin->i_mode & I_TYPE_MASK;

        if (imode == I_CHAR_SPECIAL) {
            MESSAGE driver_msg;
            driver_msg.type = DEV_OPEN;
            int dev = pin->i_start_sect;
            driver_msg.DEVICE = MINOR(dev);
            assert(MAJOR(dev) == 4);
            assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER);
            send_recv(BOTH,
                      dd_map[MAJOR(dev)].driver_nr,
                      &driver_msg);
        }
        else if (imode == I_DIRECTORY) {
            assert(pin->i_num == ROOT_INODE);
        }
        else {
            assert(pin->i_mode == I_REGULAR);
        }
    }
    else {
        return -1;
    }

    return fd;
}