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

📄 wd.c

📁 一款类linux的操作系统源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  *  Roadrunner/pk *    Copyright (C) 1989-2001  Cornfed Systems, Inc. * *  The Roadrunner/pk operating system is free software; you can *  redistribute and/or modify it under the terms of the GNU General *  Public License, version 2, as published by the Free Software *  Foundation. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public *  License along with this program; if not, write to the Free *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, *  MA 02111-1307 USA * *  More information about the Roadrunner/pk operating system of *  which this file is a part is available on the World-Wide Web *  at: http://www.cornfed.com. * */#include <dev.h>#include <dev/wd.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys.h>#include <sys/boot.h>#include <sys/buf.h>#include <sys/i8259.h>#include <sys/intr.h>#include <sys/ioctl.h>#include <sys/mutex.h>#include <sys/part.h>#include <sys/proc.h>#include <sys/time.h>#include <sys/types.h>#define WD_CONTROLLERS		1#define WD_DRIVES		1#define WDC0			(wdctab[0])#define WD0			(wdtab[0])#define WDC0_IOBASE		0x01f0/* Controller registers */#define WDC_DATA		0x0000 /* 16-bit port */#define WDC_ERR			0x0001#define WDC_FEATURE		0x0001#define WDC_SECTORCNT		0x0002#define WDC_SECTOR		0x0003#define WDC_TRACKLSB		0x0004#define WDC_TRACKMSB		0x0005#define WDC_DRVHD		0x0006#define WDC_STATUS		0x0007#define WDC_COMMAND		0x0007#define WDC_ALT_STATUS		0x0206#define WDC_CONTROL		0x0206/* Controller commands */#define WDCTL_RST		0x04   /* Controller reset */#define WDCTL_4BITHD		0x08   /* Use 4 bits for head id *//* Drive commands */#define WDCMD_NULL		0x00#define WDCMD_READP		0xec#define WDCMD_RESET		0x10/* #define WDCMD_READ           0x21 */#define WDCMD_READ		0x20#define WDCMD_WRITE		0x30/* Controller status */#define WDCS_ERR		0x01   /* Error */#define WDCS_IDX		0x02   /* Index */#define WDCS_CORR		0x04   /* Corrected data */#define WDCS_DRQ		0x08   /* Data request */#define WDCS_DSC		0x10   /* Drive seek complete */#define WDCS_DWF		0x20   /* Drive write fault */#define WDCS_DRDY		0x40   /* Drive ready */#define WDCS_BSY		0x80   /* Controller busy *//* Controller error conditions */#define WDCE_AMNF		0x01   /* Address mark not found */#define WDCE_TK0NF		0x02   /* Track 0 not found */#define WDCE_ABRT		0x04   /* Abort */#define WDCE_MCR		0x08   /* Media change requested */#define WDCE_IDNF		0x10   /* Sector id not found */#define WDCE_MC			0x20   /* Media change */#define WDCE_UNC		0x40   /* Uncorrectable data error */#define WDCE_BBK		0x80   /* Bad block *//* Timeouts (in seconds) */#define WDTIMEOUT_DRDY		5#define WDTIMEOUT_DRQ		5#define WDTIMEOUT_CMD		2/* Parameters returned by read drive parameters command */struct wdparam {    /* Drive information */    short config;		       /* General configuration bits */    u_short cylinders;		       /* Cylinders */    short reserved;    u_short heads;		       /* Heads */    short unfbytespertrk;	       /* Unformatted bytes/track */    short unfbytes;		       /* Unformatted bytes/sector */    u_short sectors;		       /* Sectors per track */    short vendorunique[3];    /* Controller information */    char serial[20];		       /* Serial number */#define WDTYPE_SINGLE           1      /* Single port, single sector buf */#define WDTYPE_DUAL             2      /* Dual port, multiple sector buf */#define WDTYPE_DUAL_CACHE       3      /* Above plus track cache */    short buffertype;		       /* Buffer type */    short buffersize;		       /* Buffer size, in 512-byte units */    short necc;			       /* ECC bytes appended */    char rev[8];		       /* Firmware revision */    char model[40];		       /* Model name */    short nsecperint;		       /* Sectors per interrupt */    short usedmovsd;		       /* Can use double word read/write?  */    char pad[418];};struct wdc {    struct mutex mutex;		       /* Controller mutex */    u_short iobase;		       /* I/O port registers base address */};struct wd {    struct wdc *wdc;		       /* Controller */    struct wdparam param;	       /* Drive parameter block */    /* Geometry */    u_int blks;			       /* Number of blocks on drive */    u_int size;			       /* Size in Mbytes */    u_int tracks;		       /* Number of tracks */    u_int heads;		       /* Number of heads */    u_int sectorspertrack;	       /* Sectors per track */    /* Partition information */    struct part parttab[PARTS];    /* Current transfer location */    u_int blkno;		       /* Current block */    u_int track;		       /* Current track */    u_int head;			       /* Current head */    u_int sector;		       /* Current sector */};static struct wdc wdctab[WD_CONTROLLERS];static struct wd wdtab[WD_DRIVES];#if _DEBUGstatic voidwd_error(char *f, u_char error){    kprintf("%s: ", f);    if (error & WDCE_BBK)	kprintf("bad block  ");    if (error & WDCE_UNC)	kprintf("uncorrectable data  ");    if (error & WDCE_MC)	kprintf("media change  ");    if (error & WDCE_IDNF)	kprintf("id not found  ");    if (error & WDCE_MCR)	kprintf("media change requested  ");    if (error & WDCE_ABRT)	kprintf("abort  ");    if (error & WDCE_TK0NF)	kprintf("track 0 not found  ");    if (error & WDCE_AMNF)	kprintf("address mark not found  ");    kprintf("\n");}#endifstatic intwd_wait(u_char cmd, u_char mask, int timeout){    time_t start;    u_char status;    for (start = time();;) {	status = inb(WD0.wdc->iobase + WDC_ALT_STATUS);	if (status & WDCS_ERR) {	    u_char error;	    error = inb(WD0.wdc->iobase + WDC_ERR);#if _DEBUG	    wd_error("wdwait", error);#endif	    switch (cmd) {	    case WDCMD_READ:		return EDEVREAD;	    case WDCMD_WRITE:		return EDEVWRITE;	    default:		return ENOSYS;	    }	}	if (!(status & WDCS_BSY) && ((status & mask) == mask))	    return 0;	if (time() - start >= timeout)	    return ETIMEDOUT;    }}static intwd_readp(struct wd *wd, char *drvstr){    int result;    /* Issue read drive parameters command */    outb(wd->wdc->iobase + WDC_DRVHD, 0xa0);    outb(wd->wdc->iobase + WDC_COMMAND, WDCMD_READP);    /* Wait for data ready */    if (!(inb(wd->wdc->iobase + WDC_ALT_STATUS) & WDCS_DRQ) &&	(result = wd_wait(WDCMD_READ, WDCS_DRQ, WDTIMEOUT_DRQ)) < 0)	return result;    /* Read parameter data */    insw(wd->wdc->iobase + WDC_DATA, (void *) &(wd->param), SECTOR_SIZE / 2);    /* Fill in drive parameters */    wd->tracks = wd->param.cylinders;    wd->heads = wd->param.heads;    wd->sectorspertrack = wd->param.sectors;    wd->blks = wd->tracks * wd->heads * wd->sectorspertrack;    wd->size = wd->blks * SECTOR_SIZE / 1048576;    kprintf("%s: %u blks (%d Mbytes) %u trks %u hds %u sec/trk\n",	    drvstr, wd->blks, wd->size,	    wd->tracks, wd->heads, wd->sectorspertrack);    return 0;}intwd_init(){    buf_t b;    struct seek seekargs;    struct dev_ops ops;    int result;    bzero(wdctab, WD_CONTROLLERS * sizeof(struct wdc));    bzero(wdtab, WD_DRIVES * sizeof(struct wd));    /* Initialize controller */    mutex_clear(&(WDC0.mutex));    WDC0.iobase = WDC0_IOBASE;    /* Initialize drive */    WD0.wdc = &WDC0;    /* Read drive parameters */    if ((result = wd_readp(&WD0, "wd0")) < 0) {#if _DEBUG	kprintf("wd_init: wd0 read drive params failed (%s)\n",		strerror(result));#endif	return result;    }    /* Read partition information */    b = bget(SECTOR_SIZE);    blen(b) = SECTOR_SIZE;    seekargs.offset = 0;    seekargs.whence = SEEK_SET;    if ((result = wd_ioctl(SEEK_BLOCK, &seekargs)) < 0) {#if _DEBUG	kprintf("wd_init: seek failed (%s)\n", strerror(result));#endif    } else if ((result = wd_read(&b)) < 0) {#if _DEBUG	kprintf("wd_init: read failed (%s)\n", strerror(result));#endif    } else {	int i;	read_parttab(bstart(b), WD0.parttab);	/* Determine which partition we booted from */	for (i = 0; i < PARTS; i++)	    if (WD0.parttab[i].off == bootparams.offset)		bootparams.part = i;    }    brel(b);    ops.init = wd0a_init;    ops.shut = wd0a_shut;    ops.ioctl = wd0a_ioctl;    ops.specific.blk_ops.read = wd0a_read;    ops.specific.blk_ops.write = wd0a_write;    dev_inst("wd0a", DEV_TYPE_BLK, &ops);    ops.init = wd0b_init;    ops.shut = wd0b_shut;    ops.ioctl = wd0b_ioctl;    ops.specific.blk_ops.read = wd0b_read;    ops.specific.blk_ops.write = wd0b_write;    dev_inst("wd0b", DEV_TYPE_BLK, &ops);    ops.init = wd0c_init;    ops.shut = wd0c_shut;    ops.ioctl = wd0c_ioctl;    ops.specific.blk_ops.read = wd0c_read;    ops.specific.blk_ops.write = wd0c_write;    dev_inst("wd0c", DEV_TYPE_BLK, &ops);    ops.init = wd0d_init;    ops.shut = wd0d_shut;    ops.ioctl = wd0d_ioctl;    ops.specific.blk_ops.read = wd0d_read;    ops.specific.blk_ops.write = wd0d_write;    dev_inst("wd0d", DEV_TYPE_BLK, &ops);    return 0;}intwd_shut(){    return 0;}intwd_ioctl(int cmd, void *args){    switch (cmd) {    case LOCK:	return mutex_lock(&(WDC0.mutex));    case UNLOCK:	return mutex_unlock(&(WDC0.mutex));    case GET_GEOMETRY:	{	    geometry_t geom;	    if (args == NULL)		return EINVAL;	    geom = (geometry_t) args;	    geom->flags = GF_PARTITIONED;	    geom->tracks = WD0.param.cylinders;	    geom->heads = WD0.param.heads;	    geom->sectorspertrack = WD0.param.sectors;	    geom->bytespersector = SECTOR_SIZE;

⌨️ 快捷键说明

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