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

📄 blockdev.c

📁 The main purpose of this project is to add a new scheduling algorithm to GeekOS and to implement a s
💻 C
字号:
/* * Block devices * Copyright (c) 2003 David H. Hovemeyer <daveho@cs.umd.edu> * $Revision: 1.17 $ *  * This is free software.  You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". */#include <geekos/errno.h>#include <geekos/screen.h>#include <geekos/string.h>#include <geekos/malloc.h>#include <geekos/int.h>#include <geekos/kthread.h>#include <geekos/synch.h>#include <geekos/blockdev.h>/*#define BLOCKDEV_DEBUG */#ifdef BLOCKDEV_DEBUG#  define Debug(args...) Print(args)#else#  define Debug(args...)#endif/* ---------------------------------------------------------------------- * Private data and functions * ---------------------------------------------------------------------- *//* * Lock protecting access/modification of block device list. */static struct Mutex s_blockdevLock;/* * List datatype for list of block devices. */DEFINE_LIST(Block_Device_List, Block_Device);IMPLEMENT_LIST(Block_Device_List, Block_Device);/* * The list in which all block devices in the system * are registered. */static struct Block_Device_List s_deviceList;/* * Perform a block IO request. * Returns 0 if successful, error code on failure. */static int Do_Request(struct Block_Device *dev, enum Request_Type type, int blockNum, void *buf){    struct Block_Request *request;    int rc;    request = Create_Request(dev, type, blockNum, buf);    if (request == 0)	return ENOMEM;    Post_Request_And_Wait(request);    rc = request->errorCode;    Free(request);    return rc;}/* ---------------------------------------------------------------------- * Public functions * ---------------------------------------------------------------------- *//* * Register a block device. * This should be called by device drivers in their Init * functions to register all detected devices. * Returns 0 if successful, error code otherwise. */int Register_Block_Device(const char *name, struct Block_Device_Ops *ops,    int unit, void *driverData, struct Thread_Queue *waitQueue,    struct Block_Request_List *requestQueue){    struct Block_Device *dev;    KASSERT(ops != 0);    KASSERT(waitQueue != 0);    KASSERT(requestQueue != 0);    dev = (struct Block_Device*) Malloc(sizeof(*dev));    if (dev == 0)	return ENOMEM;    strcpy(dev->name, name);    dev->ops = ops;    dev->unit = unit;    dev->inUse = false;    dev->driverData = driverData;    dev->waitQueue = waitQueue;    dev->requestQueue = requestQueue;    Mutex_Lock(&s_blockdevLock);    /* FIXME: handle name conflict with existing device */    Debug("Registering block device %s\n", dev->name);    Add_To_Back_Of_Block_Device_List(&s_deviceList, dev);    Mutex_Unlock(&s_blockdevLock);    return 0;}/* * Open a named block device. * Return 0 if successful, error code on error. */int Open_Block_Device(const char *name, struct Block_Device **pDev){    struct Block_Device *dev;    int rc = 0;    Mutex_Lock(&s_blockdevLock);    dev = Get_Front_Of_Block_Device_List(&s_deviceList);    while (dev != 0) {	if (strcmp(dev->name, name) == 0)	    break;	dev = Get_Next_In_Block_Device_List(dev);    }    if (dev == 0)	rc = ENODEV;    else if (dev->inUse)	rc = EBUSY;    else {	rc = dev->ops->Open(dev);	if (rc == 0) {	    *pDev = dev;	    dev->inUse = true;	}    }    Mutex_Unlock(&s_blockdevLock);    return rc;}/* * Close given block device. * Return 0 if successful, error code on error. */int Close_Block_Device(struct Block_Device *dev){    int rc;    Mutex_Lock(&s_blockdevLock);    KASSERT(dev->inUse);    rc = dev->ops->Close(dev);    if (rc == 0)	dev->inUse = false;    Mutex_Unlock(&s_blockdevLock);    return rc;}/* * Create a block device request to transfer a single block. */struct Block_Request *Create_Request(struct Block_Device *dev, enum Request_Type type,    int blockNum, void *buf){    struct Block_Request *request = Malloc(sizeof(*request));    if (request != 0) {	request->dev = dev;	request->type = type;	request->blockNum = blockNum;	request->buf = buf;	request->state = PENDING;	Clear_Thread_Queue(&request->waitQueue);    }    return request;}/* * Send a block IO request to a device and wait for it to be handled. * Returns when the driver completes the requests or signals * an error. */void Post_Request_And_Wait(struct Block_Request *request){    struct Block_Device *dev;    KASSERT(request != 0);    dev = request->dev;    KASSERT(dev != 0);    /* Send request to the driver */    Debug("Posting block device request [@%x]...\n", request);    Disable_Interrupts();    Add_To_Back_Of_Block_Request_List(dev->requestQueue, request);    Wake_Up(dev->waitQueue);    Enable_Interrupts();    /* Wait for request to be processed */    Disable_Interrupts();    while (request->state == PENDING) {	Debug("Waiting, state=%d\n", request->state);	Wait(&request->waitQueue);    }    Debug("Wait completed!\n");    Enable_Interrupts();}/* * Wait for a block request to arrive. */struct Block_Request *Dequeue_Request(struct Block_Request_List *requestQueue,    struct Thread_Queue *waitQueue){    struct Block_Request *request;    Disable_Interrupts();    while (Is_Block_Request_List_Empty(requestQueue))	Wait(waitQueue);    request = Get_Front_Of_Block_Request_List(requestQueue);    Remove_From_Front_Of_Block_Request_List(requestQueue);    Enable_Interrupts();    return request;}/* * Signal the completion of a block request. */void Notify_Request_Completion(struct Block_Request *request, enum Request_State state, int errorCode){    Disable_Interrupts();    request->state = state;    request->errorCode = errorCode;    Wake_Up(&request->waitQueue);    Enable_Interrupts();}/* * Read a block from given device. * Return 0 if successful, error code on error. */int Block_Read(struct Block_Device *dev, int blockNum, void *buf){    return Do_Request(dev, BLOCK_READ, blockNum, buf);}/* * Write a block to given device. * Return 0 if successful, error code on error. */int Block_Write(struct Block_Device *dev, int blockNum, void *buf){    return Do_Request(dev, BLOCK_WRITE, blockNum, buf);}/* * Get number of blocks in given device. */int Get_Num_Blocks(struct Block_Device *dev){    return dev->ops->Get_Num_Blocks(dev);}

⌨️ 快捷键说明

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