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

📄 sdata.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 3 页
字号:
#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 SDifc sdataifc;enum {	DbgCONFIG	= 0x01,		/* detected drive config info */	DbgIDENTIFY	= 0x02,		/* detected drive identify info */	DbgSTATE	= 0x04,		/* dump state on panic */	DbgPROBE	= 0x08,		/* trace device probing */	DbgDEBUG	= 0x80,		/* the current problem... */};#define DEBUG		(DbgDEBUG|DbgSTATE|DbgCONFIG)enum {					/* I/O ports */	Data		= 0,	Error		= 1,		/* (read) */	Features	= 1,		/* (write) */	Count		= 2,		/* sector count */	Ir		= 2,		/* interrupt reason (PACKET) */	Sector		= 3,		/* sector number, LBA<7-0> */	Cyllo		= 4,		/* cylinder low, LBA<15-8> */	Bytelo		= 4,		/* byte count low (PACKET) */	Cylhi		= 5,		/* cylinder high, LBA<23-16> */	Bytehi		= 5,		/* byte count hi (PACKET) */	Dh		= 6,		/* Device/Head, LBA<32-14> */	Status		= 7,		/* (read) */	Command		= 7,		/* (write) */	As		= 2,		/* Alternate Status (read) */	Dc		= 2,		/* Device Control (write) */};enum {					/* Error */	Med		= 0x01,		/* Media error */	Ili		= 0x01,		/* command set specific (PACKET) */	Nm		= 0x02,		/* No Media */	Eom		= 0x02,		/* command set specific (PACKET) */	Abrt		= 0x04,		/* Aborted command */	Mcr		= 0x08,		/* Media Change Request */	Idnf		= 0x10,		/* no user-accessible address */	Mc		= 0x20,		/* Media Change */	Unc		= 0x40,		/* Uncorrectable data error */	Wp		= 0x40,		/* Write Protect */	Icrc		= 0x80,		/* Interface CRC error */};enum {					/* Features */	Dma		= 0x01,		/* data transfer via DMA (PACKET) */	Ovl		= 0x02,		/* command overlapped (PACKET) */};enum {					/* Interrupt Reason */	Cd		= 0x01,		/* Command/Data */	Io		= 0x02,		/* I/O direction */	Rel		= 0x04,		/* Bus Release */};enum {					/* Device/Head */	Dev0		= 0xA0,		/* Master */	Dev1		= 0xB0,		/* Slave */	Lba		= 0x40,		/* LBA mode */};enum {					/* Status, Alternate Status */	Err		= 0x01,		/* Error */	Chk		= 0x01,		/* Check error (PACKET) */	Drq		= 0x08,		/* Data Request */	Dsc		= 0x10,		/* Device Seek Complete */	Serv		= 0x10,		/* Service */	Df		= 0x20,		/* Device Fault */	Dmrd		= 0x20,		/* DMA ready (PACKET) */	Drdy		= 0x40,		/* Device Ready */	Bsy		= 0x80,		/* Busy */};enum {					/* Command */	Cnop		= 0x00,		/* NOP */	Cdr		= 0x08,		/* Device Reset */	Crs		= 0x20,		/* Read Sectors */	Cws		= 0x30,		/* Write Sectors */	Cedd		= 0x90,		/* Execute Device Diagnostics */	Cpkt		= 0xA0,		/* Packet */	Cidpkt		= 0xA1,		/* Identify Packet Device */	Crsm		= 0xC4,		/* Read Multiple */	Cwsm		= 0xC5,		/* Write Multiple */	Csm		= 0xC6,		/* Set Multiple */	Crdq		= 0xC7,		/* Read DMA queued */	Crd		= 0xC8,		/* Read DMA */	Cwd		= 0xCA,		/* Write DMA */	Cwdq		= 0xCC,		/* Write DMA queued */	Cid		= 0xEC,		/* Identify Device */	Csf		= 0xEF,		/* Set Features */};enum {					/* Device Control */	Nien		= 0x02,		/* (not) Interrupt Enable */	Srst		= 0x04,		/* Software Reset */};enum {					/* PCI Configuration Registers */	Bmiba		= 0x20,		/* Bus Master Interface Base Address */	Idetim		= 0x40,		/* IE Timing */	Sidetim		= 0x44,		/* Slave IE Timing */	Udmactl		= 0x48,		/* Ultra DMA/33 Control */	Udmatim		= 0x4A,		/* Ultra DMA/33 Timing */};enum {					/* Bus Master IDE I/O Ports */	Bmicx		= 0,		/* Command */	Bmisx		= 2,		/* Status */	Bmidtpx		= 4,		/* Descriptor Table Pointer */};enum {					/* Bmicx */	Ssbm		= 0x01,		/* Start/Stop Bus Master */	Rwcon		= 0x08,		/* Read/Write Control */};enum {					/* Bmisx */	Bmidea		= 0x01,		/* Bus Master IDE Active */	Idedmae		= 0x02,		/* IDE DMA Error  (R/WC) */	Ideints		= 0x04,		/* IDE Interrupt Status (R/WC) */	Dma0cap		= 0x20,		/* Drive 0 DMA Capable */	Dma1cap		= 0x40,		/* Drive 0 DMA Capable */};enum {					/* Physical Region Descriptor */	PrdEOT		= 0x80000000,	/* Bus Master IDE Active */};enum {					/* offsets into the identify info. */	Iconfig		= 0,		/* general configuration */	Ilcyl		= 1,		/* logical cylinders */	Ilhead		= 3,		/* logical heads */	Ilsec		= 6,		/* logical sectors per logical track */	Iserial		= 10,		/* serial number */	Ifirmware	= 23,		/* firmware revision */	Imodel		= 27,		/* model number */	Imaxrwm		= 47,		/* max. read/write multiple sectors */	Icapabilities	= 49,		/* capabilities */	Istandby	= 50,		/* device specific standby timer */	Ipiomode	= 51,		/* PIO data transfer mode number */	Ivalid		= 53,	Iccyl		= 54,		/* cylinders if (valid&0x01) */	Ichead		= 55,		/* heads if (valid&0x01) */	Icsec		= 56,		/* sectors if (valid&0x01) */	Iccap		= 57,		/* capacity if (valid&0x01) */	Irwm		= 59,		/* read/write multiple */	Ilba0		= 60,		/* LBA size */	Ilba1		= 61,		/* LBA size */	Imwdma		= 63,		/* multiword DMA mode */	Iapiomode	= 64,		/* advanced PIO modes supported */	Iminmwdma	= 65,		/* min. multiword DMA cycle time */	Irecmwdma	= 66,		/* rec. multiword DMA cycle time */	Iminpio		= 67,		/* min. PIO cycle w/o flow control */	Iminiordy	= 68,		/* min. PIO cycle with IORDY */	Ipcktbr		= 71,		/* time from PACKET to bus release */	Iserbsy		= 72,		/* time from SERVICE to !Bsy */	Iqdepth		= 75,		/* max. queue depth */	Imajor		= 80,		/* major version number */	Iminor		= 81,		/* minor version number */	Icmdset0	= 82,		/* command sets supported */	Icmdset1	= 83,		/* command sets supported */	Icmdset2	= 84,		/* command sets supported extension */	Icmdset3	= 85,		/* command sets enabled */	Icmdset4	= 86,		/* command sets enabled */	Icmdset5	= 87,		/* command sets enabled extension */	Iudma		= 88,		/* ultra DMA mode */	Ierase		= 89,		/* time for security erase */	Ieerase		= 90,		/* time for enhanced security erase */	Ipower		= 91,		/* current advanced power management */	Irmsn		= 127,		/* removable status notification */	Istatus		= 128,		/* security status */};typedef struct Ctlr Ctlr;typedef struct Drive Drive;typedef struct Prd {	ulong	pa;			/* Physical Base Address */	int	count;} Prd;enum {	Nprd		= SDmaxio/(64*1024)+2,};typedef struct Ctlr {	int	cmdport;	int	ctlport;	int	irq;	int	tbdf;	int	bmiba;			/* bus master interface base address */	Pcidev*	pcidev;	void	(*ienable)(Ctlr*);	SDev*	sdev;	Drive*	drive[2];	Prd*	prdt;			/* physical region descriptor table */	QLock;				/* current command */	Drive*	curdrive;	int	command;		/* last command issued (debugging) */	Rendez;	int	done;	Lock;				/* register access */} Ctlr;typedef struct Drive {	Ctlr*	ctlr;	int	dev;	ushort	info[256];	int	c;			/* cylinder */	int	h;			/* head */	int	s;			/* sector */	int	sectors;		/* total */	int	secsize;		/* sector size */	int	dma;			/* DMA R/W possible */	int	dmactl;	int	rwm;			/* read/write multiple possible */	int	rwmctl;	int	pkt;			/* PACKET device, length of pktcmd */	uchar	pktcmd[16];	int	pktdma;			/* this PACKET command using dma */	uchar	sense[18];	uchar	inquiry[48];	QLock;				/* drive access */	int	command;		/* current command */	int	write;	uchar*	data;	int	dlen;	uchar*	limit;	int	count;			/* sectors */	int	block;			/* R/W bytes per block */	int	status;	int	error;} Drive;static voidpc87415ienable(Ctlr* ctlr){	Pcidev *p;	int x;	p = ctlr->pcidev;	if(p == nil)		return;	x = pcicfgr32(p, 0x40);	if(ctlr->cmdport == p->mem[0].bar)		x &= ~0x00000100;	else		x &= ~0x00000200;	pcicfgw32(p, 0x40, x);}static voidatadumpstate(Drive* drive, uchar* cmd, int lba, int count){	Prd *prd;	Pcidev *p;	Ctlr *ctlr;	int i, bmiba;	if(!(DEBUG & DbgSTATE)){		USED(drive, cmd, lba, count);		return;	}	ctlr = drive->ctlr;	print("command %2.2uX\n", ctlr->command);	print("data %8.8p limit %8.8p dlen %d status %uX error %uX\n",		drive->data, drive->limit, drive->dlen,		drive->status, drive->error);	if(cmd != nil){		print("lba %d -> %d, count %d -> %d (%d)\n",			(cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5], lba,			(cmd[7]<<8)|cmd[8], count, drive->count);	}	if(!(inb(ctlr->ctlport+As) & Bsy)){		for(i = 1; i < 7; i++)			print(" 0x%2.2uX", inb(ctlr->cmdport+i));		print(" 0x%2.2uX\n", inb(ctlr->ctlport+As));	}	if(drive->command == Cwd || drive->command == Crd){		bmiba = ctlr->bmiba;		prd = ctlr->prdt;		print("bmicx %2.2uX bmisx %2.2uX prdt %8.8p\n",			inb(bmiba+Bmicx), inb(bmiba+Bmisx), prd);		for(;;){			print("pa 0x%8.8luX count %8.8uX\n",				prd->pa, prd->count);			if(prd->count & PrdEOT)				break;			prd++;		}	}	if(ctlr->pcidev && ctlr->pcidev->vid == 0x8086){		p = ctlr->pcidev;		print("0x40: %4.4uX 0x42: %4.4uX",			pcicfgr16(p, 0x40), pcicfgr16(p, 0x42));		print("0x48: %2.2uX\n", pcicfgr8(p, 0x48));		print("0x4A: %4.4uX\n", pcicfgr16(p, 0x4A));	}}static intatadebug(int cmdport, int ctlport, char* fmt, ...){	int i, n;	va_list arg;	char buf[PRINTSIZE];	if(!(DEBUG & DbgPROBE)){		USED(cmdport, ctlport, fmt);		return 0;	}	va_start(arg, fmt);	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;	va_end(arg);	if(cmdport){		if(buf[n-1] == '\n')			n--;		n += snprint(buf+n, PRINTSIZE-n, " ataregs 0x%uX:",			cmdport);		for(i = Features; i < Command; i++)			n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",				inb(cmdport+i));		if(ctlport)			n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",				inb(ctlport+As));		n += snprint(buf+n, PRINTSIZE-n, "\n");	}	putstrn(buf, n);	return n;}static intataready(int cmdport, int ctlport, int dev, int reset, int ready, int micro){	int as;	atadebug(cmdport, ctlport, "ataready: dev %uX reset %uX ready %uX",		dev, reset, ready);	for(;;){		/*		 * Wait for the controller to become not busy and		 * possibly for a status bit to become true (usually		 * Drdy). Must change to the appropriate device		 * register set if necessary before testing for ready.		 * Always run through the loop at least once so it		 * can be used as a test for !Bsy.		 */		as = inb(ctlport+As);		if(as & reset)			;		else if(dev){			outb(cmdport+Dh, dev);			dev = 0;		}		else if(ready == 0 || (as & ready)){			atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);			return as;		}		if(micro-- <= 0){			atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);			break;		}		microdelay(1);	}	atadebug(cmdport, ctlport, "ataready: timeout");	return -1;}static intatacsfenabled(Drive* drive, vlong csf){	int cmdset, i, x;	for(i = 0; i < 3; i++){		x = (csf>>(16*i)) & 0xFFFF;		if(x == 0)			continue;		cmdset = drive->info[Icmdset3+i];		if(cmdset == 0 || cmdset == 0xFFFF)			return 0;		return cmdset & x;	}	return 0;}static intatasf(int cmdport, int ctlport, int dev, uchar* command){	int as, i;	if(ataready(cmdport, ctlport, dev, Bsy|Drq, Drdy, 108*1000) < 0)		return -1;	for(i = Features; i < Dh; i++)		outb(cmdport+i, command[i]);	outb(cmdport+Command, Csf);	microdelay(100);	as = ataready(cmdport, ctlport, 0, Bsy, Drdy|Df|Err, 109*1000);	if(as < 0 || (as & (Df|Err)))		return -1;	return 0;}static intatarwmmode(Drive* drive, int cmdport, int ctlport, int dev){	int as, maxrwm, rwm;	maxrwm = (drive->info[Imaxrwm] & 0xFF);	if(maxrwm == 0)		return 0;	/*	 * Sometimes drives come up with the current count set	 * to 0; if so, set a suitable value, otherwise believe	 * the value in Irwm if the 0x100 bit is set.	 */	if(drive->info[Irwm] & 0x100)		rwm = (drive->info[Irwm] & 0xFF);	else		rwm = 0;	if(rwm == 0)		rwm = maxrwm;	if(rwm > 16)		rwm = 16;	if(ataready(cmdport, ctlport, dev, Bsy|Drq, Drdy, 102*1000) < 0)		return 0;	outb(cmdport+Count, rwm);	outb(cmdport+Command, Csm);	microdelay(1);	as = ataready(cmdport, ctlport, 0, Bsy, Drdy|Df|Err, 1000);	inb(cmdport+Status);	if(as < 0 || (as & (Df|Err)))		return 0;	drive->rwm = rwm;	return rwm;}static intatadmamode(Drive* drive){	int dma;	/*	 * Check if any DMA mode enabled.	 * Assumes the BIOS has picked and enabled the best.	 * This is completely passive at the moment, no attempt is	 * made to ensure the hardware is correctly set up.	 */	dma = drive->info[Imwdma] & 0x0707;	drive->dma = (dma>>8) & dma;	if(drive->dma == 0 && (drive->info[Ivalid] & 0x04)){		dma = drive->info[Iudma] & 0x1F1F;		drive->dma = (dma>>8) & dma;		if(drive->dma)			drive->dma |= 'U'<<16;	}	return dma;}static intataidentify(int cmdport, int ctlport, int dev, int pkt, void* info){	int as, command, drdy;	if(pkt){		command = Cidpkt;		drdy = 0;	}	else{		command = Cid;		drdy = Drdy;	}	as = ataready(cmdport, ctlport, dev, Bsy|Drq, drdy, 103*1000);	if(as < 0)		return as;	outb(cmdport+Command, command);	microdelay(1);	as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 104*1000);	if(as < 0)		return -1;	if(as & Err)		return as;	memset(info, 0, 512);	inss(cmdport+Data, info, 256);	inb(cmdport+Status);	if(DEBUG & DbgIDENTIFY){		int i;		ushort *sp;		sp = (ushort*)info;		for(i = 0; i < 256; i++){			if(i && (i%16) == 0)				print("\n");			print("%4.4uX ", *sp);			sp++;		}		print("\n");	}	return 0;}static Drive*atadrive(int cmdport, int ctlport, int dev){	ushort *sp;	Drive *drive;	int as, i, pkt;	uchar buf[512], *p;	atadebug(0, 0, "identify: port 0x%uX dev 0x%2.2uX\n", cmdport, dev);	pkt = 1;retry:	as = ataidentify(cmdport, ctlport, dev, pkt, buf);	if(as < 0)		return nil;	if(as & Err){		if(pkt == 0)			return nil;		pkt = 0;		goto retry;	}	if((drive = malloc(sizeof(Drive))) == nil)		return nil;	drive->dev = dev;	memmove(drive->info, buf, sizeof(drive->info));	drive->sense[0] = 0x70;	drive->sense[7] = sizeof(drive->sense)-7;	drive->inquiry[2] = 2;	drive->inquiry[3] = 2;	drive->inquiry[4] = sizeof(drive->inquiry)-4;	p = &drive->inquiry[8];	sp = &drive->info[Imodel];	for(i = 0; i < 20; i++){		*p++ = *sp>>8;		*p++ = *sp++;	}	drive->secsize = 512;	if((drive->info[Iconfig] & 0xC000) == 0x8000){		if(drive->info[Iconfig] & 0x01)			drive->pkt = 16;		else			drive->pkt = 12;	}	else{		if(drive->info[Ivalid] & 0x0001){			drive->c = drive->info[Ilcyl];			drive->h = drive->info[Ilhead];			drive->s = drive->info[Ilsec];		}		else{			drive->c = drive->info[Iccyl];			drive->h = drive->info[Ichead];			drive->s = drive->info[Icsec];		}		if(drive->info[Icapabilities] & 0x0200){			drive->sectors = (drive->info[Ilba1]<<16)					 |drive->info[Ilba0];			drive->dev |= Lba;		}		else			drive->sectors = drive->c*drive->h*drive->s;		atarwmmode(drive, cmdport, ctlport, dev);	}	atadmamode(drive);		if(DEBUG & DbgCONFIG){		print("dev %2.2uX config %4.4uX capabilities %4.4uX",			dev, drive->info[Iconfig], drive->info[Icapabilities]);		print(" mwdma %4.4uX dma %8.8uX", 			drive->info[Imwdma], drive->dma);		if(drive->info[Ivalid] & 0x04)			print(" udma %4.4uX", drive->info[Iudma]);		print(" rwm %ud\n", drive->rwm);	}

⌨️ 快捷键说明

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