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

📄 sdata.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
		cmd10[0] = 0x03;		cmd10[1] = r->lun<<5;		cmd10[4] = sizeof(r->sense)-1;		drive->data = r->sense;		drive->dlen = sizeof(r->sense)-1;		drive->status = 0;		drive->error = 0;		if(drive->pkt)			reqstatus = atapktio(drive, cmd10, 6);		else			reqstatus = atagenio(drive, cmd10, 6);		if(reqstatus == SDok){			r->flags |= SDvalidsense;			atasetsense(drive, SDok, 0, 0, 0);		}	}	qunlock(drive);	r->status = status;	if(status != SDok)		return status;	/*	 * Fix up any results.	 * Many ATAPI CD-ROMs ignore the LUN field completely and	 * return valid INQUIRY data. Patch the response to indicate	 * 'logical unit not supported' if the LUN is non-zero.	 */	switch(cmdp[0]){	case 0x12:			/* inquiry */		if((p = r->data) == nil)			break;		if((cmdp[1]>>5) && (!drive->pkt || (p[0] & 0x1F) == 0x05))			p[0] = 0x7F;		/*FALLTHROUGH*/	default:		break;	}	return SDok;}static voidatainterrupt(Ureg*, void* arg){	Ctlr *ctlr;	Drive *drive;	int cmdport, len, status;	ctlr = arg;	ilock(ctlr);	if(inb(ctlr->ctlport+As) & Bsy){		iunlock(ctlr);		if(DEBUG & DbgBsy)			print("IBsy+");		return;	}	cmdport = ctlr->cmdport;	status = inb(cmdport+Status);	if((drive = ctlr->curdrive) == nil){		iunlock(ctlr);		if((DEBUG & DbgINL) && ctlr->command != Cedd)			print("Inil%2.2uX+", ctlr->command);		return;	}	if(status & Err)		drive->error = inb(cmdport+Error);	else switch(drive->command){	default:		drive->error = Abrt;		break;	case Crs:	case Crsm:		if(!(status & Drq)){			drive->error = Abrt;			break;		}		len = drive->block;		if(drive->data+len > drive->limit)			len = drive->limit-drive->data;		inss(cmdport+Data, drive->data, len/2);		drive->data += len;		if(drive->data >= drive->limit)			ctlr->done = 1;		break;	case Cws:	case Cwsm:		len = drive->block;		if(drive->data+len > drive->limit)			len = drive->limit-drive->data;		drive->data += len;		if(drive->data >= drive->limit){			ctlr->done = 1;			break;		}		if(!(status & Drq)){			drive->error = Abrt;			break;		}		len = drive->block;		if(drive->data+len > drive->limit)			len = drive->limit-drive->data;		outss(cmdport+Data, drive->data, len/2);		break;	case Cpkt:		atapktinterrupt(drive);		break;	case Crd:	case Cwd:		atadmainterrupt(drive, drive->count*drive->secsize);		break;	case Cstandby:		ctlr->done = 1;		break;	}	iunlock(ctlr);	if(drive->error){		status |= Err;		ctlr->done = 1;	}	if(ctlr->done){		ctlr->curdrive = nil;		drive->status = status;		wakeup(ctlr);	}}static SDev*atapnp(void){	Ctlr *ctlr;	Pcidev *p;	SDev *legacy[2], *sdev, *head, *tail;	int channel, ispc87415, maxio, pi, r, span;	legacy[0] = legacy[1] = head = tail = nil;	if(sdev = ataprobe(0x1F0, 0x3F4, IrqATA0)){		head = tail = sdev;		legacy[0] = sdev;	}	if(sdev = ataprobe(0x170, 0x374, IrqATA1)){		if(head != nil)			tail->next = sdev;		else			head = sdev;		tail = sdev;		legacy[1] = sdev;	}	p = nil;	while(p = pcimatch(p, 0, 0)){		/*		 * Look for devices with the correct class and sub-class		 * code and known device and vendor ID; add native-mode		 * channels to the list to be probed, save info for the		 * compatibility mode channels.		 * Note that the legacy devices should not be considered		 * PCI devices by the interrupt controller.		 * For both native and legacy, save info for busmastering		 * if capable.		 * Promise Ultra ATA/66 (PDC20262) appears to		 * 1) give a sub-class of 'other mass storage controller'		 *    instead of 'IDE controller', regardless of whether it's		 *    the only controller or not;		 * 2) put 0 in the programming interface byte (probably		 *    as a consequence of 1) above).		 * Sub-class code 0x04 is 'RAID controller', e.g. VIA VT8237.		 */		if(p->ccrb != 0x01)			continue;		if(p->ccru != 0x01 && p->ccru != 0x04 && p->ccru != 0x80)			continue;		pi = p->ccrp;		ispc87415 = 0;		maxio = 0;		span = BMspan;		switch((p->did<<16)|p->vid){		default:			continue;		case (0x0002<<16)|0x100B:	/* NS PC87415 */			/*			 * Disable interrupts on both channels until			 * after they are probed for drives.			 * This must be called before interrupts are			 * enabled because the IRQ may be shared.			 */			ispc87415 = 1;			pcicfgw32(p, 0x40, 0x00000300);			break;		case (0x1000<<16)|0x1042:	/* PC-Tech RZ1000 */			/*			 * Turn off prefetch. Overkill, but cheap.			 */			r = pcicfgr32(p, 0x40);			r &= ~0x2000;			pcicfgw32(p, 0x40, r);			break;		case (0x4D38<<16)|0x105A:	/* Promise PDC20262 */		case (0x4D30<<16)|0x105A:	/* Promise PDC202xx */		case (0x4D68<<16)|0x105A:	/* Promise PDC20268 */		case (0x4D69<<16)|0x105A:	/* Promise Ultra/133 TX2 */		case (0x3373<<16)|0x105A:	/* Promise 20378 RAID */		case (0x3149<<16)|0x1106:	/* VIA VT8237 SATA/RAID */		case (0x3112<<16)|0x1095:	/* SiI 3112 SATA/RAID */			maxio = 15;			span = 8*1024;			/*FALLTHROUGH*/		case (0x3114<<16)|0x1095:	/* SiI 3114 SATA/RAID */			pi = 0x85;			break;		case (0x0004<<16)|0x1103:	/* HighPoint HPT366 */			pi = 0x85;			/*			 * Turn off fast interrupt prediction.			 */			if((r = pcicfgr8(p, 0x51)) & 0x80)				pcicfgw8(p, 0x51, r & ~0x80);			if((r = pcicfgr8(p, 0x55)) & 0x80)				pcicfgw8(p, 0x55, r & ~0x80);			break;		case (0x0640<<16)|0x1095:	/* CMD 640B */			/*			 * Bugfix code here...			 */			break;		case (0x7441<<16)|0x1022:	/* AMD 768 */			/*			 * Set:			 *	0x41	prefetch, postwrite;			 *	0x43	FIFO configuration 1/2 and 1/2;			 *	0x44	status register read retry;			 *	0x46	DMA read and end of sector flush.			 */			r = pcicfgr8(p, 0x41);			pcicfgw8(p, 0x41, r|0xF0);			r = pcicfgr8(p, 0x43);			pcicfgw8(p, 0x43, (r & 0x90)|0x2A);			r = pcicfgr8(p, 0x44);			pcicfgw8(p, 0x44, r|0x08);			r = pcicfgr8(p, 0x46);			pcicfgw8(p, 0x46, (r & 0x0C)|0xF0);			/*FALLTHROUGH*/		case (0x7469<<16)|0x1022:	/* AMD 3111 */			/*			 * This can probably be lumped in with the 768 above.			 */			/*FALLTHROUGH*/		case (0x01BC<<16)|0x10DE:	/* nVidia nForce1 */		case (0x0065<<16)|0x10DE:	/* nVidia nForce2 */		case (0x0085<<16)|0x10DE:	/* nVidia nForce2 MCP */		case (0x00D5<<16)|0x10DE:	/* nVidia nForce3 */		case (0x00E5<<16)|0x10DE:	/* nVidia nForce3 Pro */		case (0x0035<<16)|0x10DE:	/* nVidia nForce3 MCP */		case (0x0053<<16)|0x10DE:	/* nVidia nForce4 */		case (0x0054<<16)|0x10DE:	/* nVidia nForce4 SATA */		case (0x0055<<16)|0x10DE:	/* nVidia nForce4 SATA */		case (0x0266<<16)|0x10DE:	/* nVidia nForce4 430 SATA */		case (0x0267<<16)|0x10DE:	/* nVidia nForce4 430 SATA */			/*			 * Ditto, although it may have a different base			 * address for the registers (0x50?).			 */			/*FALLTHROUGH*/		case (0x4376<<16)|0x1002:	/* ATI Radeon Xpress 200M */			break;		case (0x0211<<16)|0x1166:	/* ServerWorks IB6566 */			{				Pcidev *sb;				sb = pcimatch(nil, 0x1166, 0x0200);				if(sb == nil)					break;				r = pcicfgr32(sb, 0x64);				r &= ~0x2000;				pcicfgw32(sb, 0x64, r);			}			span = 32*1024;			break;		case (0x5229<<16)|0x10B9:	/* ALi M1543 */		case (0x5288<<16)|0x10B9:	/* ALi M5288 SATA */			/*FALLTHROUGH*/		case (0x5513<<16)|0x1039:	/* SiS 962 */		case (0x0646<<16)|0x1095:	/* CMD 646 */		case (0x0571<<16)|0x1106:	/* VIA 82C686 */		case (0x1230<<16)|0x8086:	/* 82371FB (PIIX) */		case (0x7010<<16)|0x8086:	/* 82371SB (PIIX3) */		case (0x7111<<16)|0x8086:	/* 82371[AE]B (PIIX4[E]) */		case (0x2411<<16)|0x8086:	/* 82801AA (ICH) */		case (0x2421<<16)|0x8086:	/* 82801AB (ICH0) */		case (0x244A<<16)|0x8086:	/* 82801BA (ICH2, Mobile) */		case (0x244B<<16)|0x8086:	/* 82801BA (ICH2, High-End) */		case (0x248A<<16)|0x8086:	/* 82801CA (ICH3, Mobile) */		case (0x248B<<16)|0x8086:	/* 82801CA (ICH3, High-End) */		case (0x24CA<<16)|0x8086:	/* 82801DBM (ICH4, Mobile) */		case (0x24CB<<16)|0x8086:	/* 82801DB (ICH4, High-End) */		case (0x24DB<<16)|0x8086:	/* 82801EB (ICH5) */		case (0x266F<<16)|0x8086:	/* 82801FB (ICH6) */		case (0x27C4<<16)|0x8086:	/* 82801GBM SATA (ICH7) */		case (0x27C5<<16)|0x8086:	/* 82801GBM SATA AHCI (ICH7) */			break;		}		for(channel = 0; channel < 2; channel++){			if(pi & (1<<(2*channel))){				sdev = ataprobe(p->mem[0+2*channel].bar & ~0x01,						p->mem[1+2*channel].bar & ~0x01,						p->intl);				if(sdev == nil)					continue;				ctlr = sdev->ctlr;				if(ispc87415) {					ctlr->ienable = pc87415ienable;					print("pc87415disable: not yet implemented\n");				}				if(head != nil)					tail->next = sdev;				else					head = sdev;				tail = sdev;				ctlr->tbdf = p->tbdf;			}			else if((sdev = legacy[channel]) == nil)				continue;			else				ctlr = sdev->ctlr;			ctlr->pcidev = p;			ctlr->maxio = maxio;			ctlr->span = span;			if(!(pi & 0x80))				continue;			ctlr->bmiba = (p->mem[4].bar & ~0x01) + channel*8;		}	}if(0){	int port;	ISAConf isa;	/*	 * Hack for PCMCIA drives.	 * This will be tidied once we figure out how the whole	 * removeable device thing is going to work.	 */	memset(&isa, 0, sizeof(isa));	isa.port = 0x180;		/* change this for your machine */	isa.irq = 11;			/* change this for your machine */	port = isa.port+0x0C;	channel = pcmspecial("MK2001MPL", &isa);	if(channel == -1)		channel = pcmspecial("SunDisk", &isa);	if(channel == -1){		isa.irq = 10;		channel = pcmspecial("CF", &isa);	}	if(channel == -1){		isa.irq = 10;		channel = pcmspecial("OLYMPUS", &isa);	}	if(channel == -1){		port = isa.port+0x204;		channel = pcmspecial("ATA/ATAPI", &isa);	}	if(channel >= 0 && (sdev = ataprobe(isa.port, port, isa.irq)) != nil){		if(head != nil)			tail->next = sdev;		else			head = sdev;	}}	return head;}static SDev*atalegacy(int port, int irq){	return ataprobe(port, port+0x204, irq);}static intataenable(SDev* sdev){	Ctlr *ctlr;	char name[32];	ctlr = sdev->ctlr;	if(ctlr->bmiba){#define ALIGN	(4 * 1024)		if(ctlr->pcidev != nil)			pcisetbme(ctlr->pcidev);		ctlr->prdt = mallocalign(Nprd*sizeof(Prd), 4, 0, 4*1024);	}	snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name);	intrenable(ctlr->irq, atainterrupt, ctlr, ctlr->tbdf, name);	outb(ctlr->ctlport+Dc, 0);	if(ctlr->ienable)		ctlr->ienable(ctlr);	return 1;}static intatadisable(SDev *sdev){	Ctlr *ctlr;	char name[32];	ctlr = sdev->ctlr;	outb(ctlr->ctlport+Dc, Nien);		/* disable interrupts */	if (ctlr->idisable)		ctlr->idisable(ctlr);	snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name);	intrdisable(ctlr->irq, atainterrupt, ctlr, ctlr->tbdf, name);	if (ctlr->bmiba) {		if (ctlr->pcidev)			pciclrbme(ctlr->pcidev);		free(ctlr->prdt);	}	return 0;}static intatarctl(SDunit* unit, char* p, int l){	int n;	Ctlr *ctlr;	Drive *drive;	if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil)		return 0;	drive = ctlr->drive[unit->subno];	qlock(drive);	n = snprint(p, l, "config %4.4uX capabilities %4.4uX",		drive->info[Iconfig], drive->info[Icapabilities]);	if(drive->dma)		n += snprint(p+n, l-n, " dma %8.8uX dmactl %8.8uX",			drive->dma, drive->dmactl);	if(drive->rwm)		n += snprint(p+n, l-n, " rwm %ud rwmctl %ud",			drive->rwm, drive->rwmctl);	if(drive->flags&Lba48)		n += snprint(p+n, l-n, " lba48always %s",			(drive->flags&Lba48always) ? "on" : "off");	n += snprint(p+n, l-n, "\n");	if(drive->sectors){		n += snprint(p+n, l-n, "geometry %lld %d",			drive->sectors, drive->secsize);		if(drive->pkt == 0)			n += snprint(p+n, l-n, " %d %d %d",				drive->c, drive->h, drive->s);		n += snprint(p+n, l-n, "\n");	}	qunlock(drive);	return n;}static intatawctl(SDunit* unit, Cmdbuf* cb){	int period;	Ctlr *ctlr;	Drive *drive;	if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil)		return 0;	drive = ctlr->drive[unit->subno];	qlock(drive);	if(waserror()){		qunlock(drive);		nexterror();	}	/*	 * Dma and rwm control is passive at the moment,	 * i.e. it is assumed that the hardware is set up	 * correctly already either by the BIOS or when	 * the drive was initially identified.	 */	if(strcmp(cb->f[0], "dma") == 0){		if(cb->nf != 2 || drive->dma == 0)			error(Ebadctl);		if(strcmp(cb->f[1], "on") == 0)			drive->dmactl = drive->dma;		else if(strcmp(cb->f[1], "off") == 0)			drive->dmactl = 0;		else			error(Ebadctl);	}	else if(strcmp(cb->f[0], "rwm") == 0){		if(cb->nf != 2 || drive->rwm == 0)			error(Ebadctl);		if(strcmp(cb->f[1], "on") == 0)			drive->rwmctl = drive->rwm;		else if(strcmp(cb->f[1], "off") == 0)			drive->rwmctl = 0;		else			error(Ebadctl);	}	else if(strcmp(cb->f[0], "standby") == 0){		switch(cb->nf){		default:			error(Ebadctl);		case 2:			period = strtol(cb->f[1], 0, 0);			if(period && (period < 30 || period > 240*5))				error(Ebadctl);			period /= 5;			break;		}		if(atastandby(drive, period) != SDok)			error(Ebadctl);	}	else if(strcmp(cb->f[0], "lba48always") == 0){		if(cb->nf != 2 || !(drive->flags&Lba48))			error(Ebadctl);		if(strcmp(cb->f[1], "on") == 0)			drive->flags |= Lba48always;		else if(strcmp(cb->f[1], "off") == 0)			drive->flags &= ~Lba48always;		else			error(Ebadctl);	}	else		error(Ebadctl);	qunlock(drive);	poperror();	return 0;}SDifc sdataifc = {	"ata",				/* name */	atapnp,				/* pnp */	atalegacy,			/* legacy */	ataenable,			/* enable */	atadisable,			/* disable */	scsiverify,			/* verify */	scsionline,			/* online */	atario,				/* rio */	atarctl,			/* rctl */	atawctl,			/* wctl */	scsibio,			/* bio */	ataprobew,			/* probe */	ataclear,			/* clear */	atastat,			/* stat */};

⌨️ 快捷键说明

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