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

📄 devsd.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
字号:
/* * Storage Device. */#include "u.h"#include "mem.h"#include "lib.h"#include "dat.h"#include "fns.h"#include "io.h"#include "ureg.h"#include "error.h"#include "sd.h"#include "dosfs.h"extern SDifc* sdifc[];static SDev* sdlist;static SDunit** sdunit;static int sdnunit;enum {	Rawcmd,	Rawdata,	Rawstatus,};voidsdaddpart(SDunit* unit, char* name, ulong start, ulong end){	SDpart *pp;	int i, partno;//print("add %d %s %s %ld %ld\n", unit->npart, unit->name, name, start, end);	/*	 * 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(strcmp(name, pp->name) == 0){				if(pp->start == start && pp->end == end)					return;			}		}	}	else{		if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil)			return;		partno = 0;	}	/*	 * Check there is a free slot and size and extent are valid.	 */	if(partno == -1 || start > end || end > unit->sectors)		return;	pp = &unit->part[partno];	pp->start = start;	pp->end = end;	strncpy(pp->name, name, NAMELEN);	pp->valid = 1;	unit->npart++;}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)		return;	pp->valid = 0;	unit->npart--;	if(unit->npart == 0){		free(unit->part);		unit->part = nil;	}}static intsdinitpart(SDunit* unit){	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 == nil || unit->dev->ifc->online(unit) == 0)		return 0;	sdaddpart(unit, "data", 0, unit->sectors);	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){		if((unit = malloc(sizeof(SDunit))) == nil){			qunlock(&sdqlock);			return nil;		}		if(sdev->enabled == 0 && sdev->ifc->enable)			sdev->ifc->enable(sdev);		sdev->enabled = 1;		snprint(unit->name, NAMELEN, "sd%c%d", sdev->idno, 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;}intsdinit(void){	ulong m;	int i;	SDev *sdev, *tail;	SDunit *unit;	/*	 * 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((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 0;	if((sdunit = malloc(sdnunit*sizeof(SDunit*))) == nil)		return 0;	for(i = 0; sdifc[i] != nil; i++){		if(sdifc[i]->id)			sdifc[i]->id(sdlist);	}	m = 0;	for(i=0; i<sdnunit && i < 32; i++) {		unit = sdindex2unit(i);		sdinitpart(unit);		partition(unit);		if(unit->npart > 0)	/* BUG */			m |= (1<<i);	}	return m;}voidsdinitdev(int i, char *s){	SDunit *unit;	unit = sdindex2unit(i);	strcpy(s, unit->name);}SDpart*sdfindpart(SDunit *unit, char *name){	int i;	for(i=0; i<unit->npart; i++) {		if(strcmp(unit->part[i].name, name) == 0)			return &unit->part[i];	}	return nil;}typedef struct Scsicrud Scsicrud;struct Scsicrud {	Dos;	ulong offset;	SDunit *unit;	SDpart *part;};longsdread(Dos *vdos, void *v, long n){	Scsicrud *dos;	long x;	dos = (Scsicrud*)vdos;	x = sdbio(dos->unit, dos->part, v, n, dos->offset);	if(x > 0)		dos->offset += x;	return x;}longsdseek(Dos *vdos, long seek){	return ((Scsicrud*)vdos)->offset = seek;}void*sdgetdospart(int i, char *s){	SDunit *unit;	SDpart *p;	Scsicrud *dos;	unit = sdindex2unit(i);	if((p = sdfindpart(unit, s)) == nil)		return nil;	if(p->dos == nil) {		dos = malloc(sizeof(Scsicrud));		dos->dev = i;		dos->read = sdread;		dos->seek = sdseek;		dos->start = 0;		dos->unit = unit;		dos->part = p;		if(dosinit(dos) < 0)			return nil;		p->dos = dos;	}	return p->dos;}/* * Leave partitions around for devsd to pick up. * (Needed by boot process; more extensive  * partitioning is done by termrc or cpurc). */voidsdaddconf(int i){	SDunit *unit;	SDpart *pp;	unit = sdindex2unit(i);		/*	 * If there were no partitions (just data and partition), don't bother.	 */	if(unit->npart <= 2)		return;	addconf("%spart=", unit->name);	for(i=1, pp=&unit->part[i]; i<unit->npart; i++, pp++)	/* skip 0, which is "data" */		addconf("%s%s %ld %ld", i==1 ? "" : "/", pp->name,			pp->start, pp->end);	addconf("\n");}intsdboot(int dev, char *pname, Boot *b){	char *file;	Dos *dos;	if((file = strchr(pname, '!')) == nil) {		print("syntax is sdC0!partition!file\n");		return -1;	}	*file++ = '\0';	dos = sdgetdospart(dev, pname);	if(dos == nil) {		print("no such FAT partition %s!%s\n", sdindex2unit(dev)->name, pname);		return -1;	}	return dosboot(dos, file, b);}longsdbio(SDunit *unit, SDpart *pp, void* va, long len, vlong off){	long l;	ulong bno, max, nb, offset;	static uchar *b;	char *a;	static ulong bsz;	a = va;memset(a, 0xDA, len);	qlock(&unit->ctl);	if(unit->changed){		qunlock(&unit->ctl);		return 0;	}	/*	 * Check the request is within bounds.	 * Removeable drives are locked throughout the I/O	 * in case the media changes unexpectedly.	 * Non-removeable drives are not locked during the I/O	 * to allow the hardware to optimise if it can; this is	 * a little fast and loose.	 * It's assumed that non-removable media parameters	 * (sectors, secsize) can't change once the drive has	 * been brought online.	 */	bno = (off/unit->secsize) + pp->start;	nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;	max = SDmaxio/unit->secsize;	if(nb > max)		nb = max;	if(bno+nb > pp->end)		nb = pp->end - bno;	if(bno >= pp->end || nb == 0){		qunlock(&unit->ctl);		return 0;	}	if(!(unit->inquiry[1] & 0x80))		qunlock(&unit->ctl);	if(bsz < nb*unit->secsize){		b = malloc(nb*unit->secsize);		bsz = nb*unit->secsize;	}//	b = sdmalloc(nb*unit->secsize);//	if(b == nil)//		return 0;	offset = off%unit->secsize;	if((l = unit->dev->ifc->bio(unit, 0, 0, a, nb, bno)) < 0) {//		sdfree(b);		return 0;	}	if(l < offset)		len = 0;	else if(len > l - offset)		len = l - offset;//	sdfree(b);	if(unit->inquiry[1] & 0x80)		qunlock(&unit->ctl);	return len;}#ifdef DMAlongsdrio(SDreq *r, void* a, long n){	if(n >= SDmaxio || n < 0)		return 0;	r->data = nil;	if(n){		if((r->data = malloc(n)) == nil)			return 0;		if(r->write)			memmove(r->data, a, n);	}	r->dlen = n;	if(r->unit->dev->ifc->rio(r) != SDok){// cgascreenputs("1", 1);		if(r->data != nil){			sdfree(r->data);			r->data = nil;		}		return 0;	}// cgascreenputs("2", 1);	if(!r->write && r->rlen > 0)		memmove(a, r->data, r->rlen);// cgascreenputs("3", 1);	if(r->data != nil){		sdfree(r->data);		r->data = nil;	}// cgascreenputs("4", 1);	return r->rlen;}#endif /* DMA */voidsleep(void*, int (*fn)(void*), void *v){	int x;	x = spllo();	while(!fn(v))		;	splx(x);	return;}voidtsleep(void*, int (*fn)(void*), void *v, int msec){	int x;	ulong start;	x = spllo();	for(start = m->ticks; TK2MS(m->ticks - start) < msec		&& !fn(v); )		;	splx(x);	return;}void*sdmalloc(void *p, ulong sz){	if(p != nil) {		memset(p, 0, sz);		return p;	}	return malloc(sz);}extern SDifc sdataifc;SDifc* sdifc[] = {	&sdataifc,	nil,};

⌨️ 快捷键说明

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