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

📄 devsd.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Storage Device. */#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "ureg.h"#include "../port/error.h"#include "sd.h"extern Dev sddevtab;extern SDifc* sdifc[];static QLock sdqlock;static SDev* sdlist;static SDunit** sdunit;static int* sdunitflg;static int sdnunit;enum {	Rawcmd,	Rawdata,	Rawstatus,};enum {	Qtopdir		= 1,		/* top level directory */	Qtopbase,	Qunitdir,			/* directory per unit */	Qunitbase,	Qctl		= Qunitbase,	Qraw,	Qpart,};#define TYPE(q)		((q).path & 0x0F)#define PART(q)		(((q).path>>4) & 0x0F)#define UNIT(q)		(((q).path>>8) & 0xFF)#define QID(u, p, t)	(((u)<<8)|((p)<<4)|(t))static voidsdaddpart(SDunit* unit, char* name, ulong start, ulong end){	SDpart *pp;	int i, partno;	/*	 * Check name not already used	 * and look for a free slot.	 */	if(unit->part != nil){		partno = -1;		for(i = 0; i < SDnpart; i++){			pp = &unit->part[i];			if(!pp->valid){				if(partno == -1)					partno = i;				break;			}			if(strncmp(name, pp->name, NAMELEN) == 0){				if(pp->start == start && pp->end == end)					return;				error(Ebadctl);			}		}	}	else{		if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil)			error(Enomem);		partno = 0;	}	/*	 * Check there is a free slot and size and extent are valid.	 */	if(partno == -1 || start > end || end > unit->sectors)		error(Eio);	pp = &unit->part[partno];	pp->start = start;	pp->end = end;	strncpy(pp->name, name, NAMELEN);	strncpy(pp->user, eve, NAMELEN);	pp->perm = 0640;	pp->valid = 1;	unit->npart++;}static voidsddelpart(SDunit* unit,  char* name){	int i;	SDpart *pp;	/*	 * Look for the partition to delete.	 * Can't delete if someone still has it open.	 * If it's the last valid partition zap the	 * whole table.	 */	pp = unit->part;	for(i = 0; i < SDnpart; i++){		if(strncmp(name, pp->name, NAMELEN) == 0)			break;		pp++;	}	if(i >= SDnpart)		error(Ebadctl);	if(strncmp(up->user, pp->user, NAMELEN) && !iseve())		error(Eperm);	if(pp->nopen)		error(Einuse);	pp->valid = 0;	unit->npart--;	if(unit->npart == 0){		free(unit->part);		unit->part = nil;	}}static intsdinitpart(SDunit* unit){	int nf;	ulong start, end;	char *f[4], *p, *q, buf[10];	unit->sectors = unit->secsize = 0;	unit->npart = 0;	if(unit->part){		free(unit->part);		unit->part = nil;	}	if(unit->inquiry[0] & 0xC0)		return 0;	switch(unit->inquiry[0] & 0x1F){	case 0x00:			/* DA */	case 0x04:			/* WORM */	case 0x05:			/* CD-ROM */	case 0x07:			/* MO */		break;	default:		return 0;	}	if(unit->dev->ifc->online)		unit->dev->ifc->online(unit);	if(unit->sectors){		sdaddpart(unit, "data", 0, unit->sectors);			/*		 * Use partitions passed from boot program,		 * e.g.		 *	sdC0part=dos 63 123123/plan9 123123 456456		 * This happens before /boot sets hostname so the		 * partitions will have the null-string for user.		 * The gen functions patch it up.		 */		snprint(buf, sizeof buf, "%spart", unit->name);		for(p = getconf(buf); p != nil; p = q){			if(q = strchr(p, '/'))				*q++ = '\0';			nf = getfields(p, f, nelem(f), 1, " \t\r");			if(nf < 3)				continue;					start = strtoul(f[1], 0, 0);			end = strtoul(f[2], 0, 0);			if(!waserror()){				sdaddpart(unit, f[0], start, end);				poperror();			}		}				}	return 1;}static SDunit*sdgetunit(SDev* sdev, int subno){	int index;	SDunit *unit;	/*	 * Associate a unit with a given device and sub-unit	 * number on that device.	 * The device will be probed if it has not already been	 * successfully accessed.	 */	qlock(&sdqlock);	index = sdev->index+subno;	unit = sdunit[index];	if(unit == nil){		/*		 * Probe the unit only once. This decision		 * may be a little severe and reviewed later.		 */		if(sdunitflg[index]){			qunlock(&sdqlock);			return nil;		}		if((unit = malloc(sizeof(SDunit))) == nil){			qunlock(&sdqlock);			return nil;		}		sdunitflg[index] = 1;		if(sdev->enabled == 0 && sdev->ifc->enable)			sdev->ifc->enable(sdev);		sdev->enabled = 1;		snprint(unit->name, NAMELEN, "%s%d", sdev->name, subno);		unit->subno = subno;		unit->dev = sdev;		/*		 * No need to lock anything here as this is only		 * called before the unit is made available in the		 * sdunit[] array.		 */		if(unit->dev->ifc->verify(unit) == 0){			qunlock(&sdqlock);			free(unit);			return nil;		}		sdunit[index] = unit;	}	qunlock(&sdqlock);	return unit;}static SDunit*sdindex2unit(int index){	SDev *sdev;	/*	 * Associate a unit with a given index into the top-level	 * device directory.	 * The device will be probed if it has not already been	 * successfully accessed.	 */	for(sdev = sdlist; sdev != nil; sdev = sdev->next){		if(index >= sdev->index && index < sdev->index+sdev->nunit)			return sdgetunit(sdev, index-sdev->index);	}	return nil;}static voidsdreset(void){	int i;	SDev *sdev, *tail;	/*	 * Probe all configured controllers and make a list	 * of devices found, accumulating a possible maximum number	 * of units attached and marking each device with an index	 * into the linear top-level directory array of units.	 */	tail = nil;	for(i = 0; sdifc[i] != nil; i++){		if(sdifc[i]->pnp == nil || (sdev = sdifc[i]->pnp()) == nil)			continue;		if(sdlist != nil)			tail->next = sdev;		else			sdlist = sdev;		for(tail = sdev; tail->next != nil; tail = tail->next){			sdev->index = sdnunit;			sdnunit += tail->nunit;		}		tail->index = sdnunit;		sdnunit += tail->nunit;	}	/*	 * Legacy and option code goes here. This will be hard...	 */	/*	 * The maximum number of possible units is known, allocate	 * placeholders for their datastructures; the units will be	 * probed and structures allocated when attached.	 * Allocate controller names for the different types.	 */	if(sdnunit == 0)		return;	if((sdunit = malloc(sdnunit*sizeof(SDunit*))) == nil)		return;	if((sdunitflg = malloc(sdnunit*sizeof(int))) == nil){		free(sdunit);		sdunit = nil;		return;	}	for(i = 0; sdifc[i] != nil; i++){		/*		 * BUG: no check is made here or later when a		 * unit is attached that the id and name are set.		 */		if(sdifc[i]->id)			sdifc[i]->id(sdlist);	}}static intsd2gen(Chan* c, int i, Dir* dp){	Qid q;	vlong l;	SDpart *pp;	SDunit *unit;	switch(i){	case Qctl:		q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qctl), c->qid.vers};		devdir(c, q, "ctl", 0, eve, 0640, dp);		return 1;	case Qraw:		q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qraw), c->qid.vers};		devdir(c, q, "raw", 0, eve, CHEXCL|0600, dp);		return 1;	case Qpart:		unit = sdunit[UNIT(c->qid)];		if(unit->changed)			break;		pp = &unit->part[PART(c->qid)];		l = (pp->end - pp->start) * (vlong)unit->secsize;		q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qpart), c->qid.vers};		if(pp->user[0] == '\0')			strncpy(pp->user, eve, NAMELEN);		devdir(c, q, pp->name, l, pp->user, pp->perm, dp);		return 1;	}		return -1;}static intsd1gen(Chan*, int i, Dir*){	switch(i){	default:		return -1;	}	return -1;}static intsdgen(Chan* c, Dirtab*, int, int s, Dir* dp){	Qid q;	vlong l;	int i, r;	SDpart *pp;	SDunit *unit;	char name[NAMELEN];	switch(TYPE(c->qid)){	case Qtopdir:		if(s == DEVDOTDOT){			q = (Qid){QID(0, 0, Qtopdir)|CHDIR, 0};			snprint(name, NAMELEN, "#%C", sddevtab.dc);			devdir(c, q, name, 0, eve, 0555, dp);			return 1;		}		if(s < sdnunit){			if(sdunit[s] == nil && sdindex2unit(s) == nil)				return 0;			q = (Qid){QID(s, 0, Qunitdir)|CHDIR, 0};			devdir(c, q, sdunit[s]->name, 0, eve, 0555, dp);			return 1;		}		s -= sdnunit;		return sd1gen(c, s+Qtopbase, dp);	case Qunitdir:		if(s == DEVDOTDOT){			q = (Qid){QID(0, 0, Qtopdir)|CHDIR, 0};			snprint(name, NAMELEN, "#%C", sddevtab.dc);			devdir(c, q, name, 0, eve, 0555, dp);			return 1;		}		unit = sdunit[UNIT(c->qid)];		qlock(&unit->ctl);		if(!unit->changed && unit->sectors == 0)			sdinitpart(unit);		i = s+Qunitbase;		if(i < Qpart){			r = sd2gen(c, i, dp);			qunlock(&unit->ctl);			return r;		}		i -= Qpart;		if(unit->npart == 0 || i >= SDnpart){			qunlock(&unit->ctl);			break;		}		pp = &unit->part[i];		if(unit->changed || !pp->valid){			qunlock(&unit->ctl);			return 0;		}		l = (pp->end - pp->start) * (vlong)unit->secsize;		q = (Qid){QID(UNIT(c->qid), i, Qpart), c->qid.vers};		if(pp->user[0] == '\0')			strncpy(pp->user, eve, NAMELEN);		devdir(c, q, pp->name, l, pp->user, pp->perm, dp);		qunlock(&unit->ctl);		return 1;	case Qraw:	case Qctl:	case Qpart:		unit = sdunit[UNIT(c->qid)];		qlock(&unit->ctl);		r = sd2gen(c, TYPE(c->qid), dp);		qunlock(&unit->ctl);		return r;	default:		break;	}	return -1;}static Chan*sdattach(char* spec){	Chan *c;	char *p;	SDev *sdev;	int idno, subno;	if(sdnunit == 0 || *spec == '\0'){		c = devattach(sddevtab.dc, spec);		c->qid = (Qid){QID(0, 0, Qtopdir)|CHDIR, 0};		return c;	}	if(spec[0] != 's' || spec[1] != 'd')		error(Ebadspec);	idno = spec[2];	subno = strtol(&spec[3], &p, 0);	if(p == &spec[3])		error(Ebadspec);	for(sdev = sdlist; sdev != nil; sdev = sdev->next){		if(sdev->idno == idno && subno < sdev->nunit)			break;

⌨️ 快捷键说明

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