~kris/9p

9hist

0da9e3756462883cdc09ff869bc4760c5f89d587 — David du Colombier 27 years ago 2d32370
Plan 9 from Bell Labs 1999-03-01
10 files changed, 394 insertions(+), 234 deletions(-)

M carrera/clock.c
M carrera/dat.h
M pc/clock.c
M pc/i8259.c
M pc/io.h
M pc/mp.c
M pc/pci.c
M pc/pcmciamodem.c
M pc/scsi.c
M pc/trap.c
M carrera/clock.c => carrera/clock.c +34 -4
@@ 17,6 17,8 @@ typedef struct Clock0link {

static Clock0link *clock0link;
static Lock clock0lock;
static ulong		incr;		/* compare register increment */
static uvlong		fasthz;		/* ticks/sec of fast clock */

void
addclock0link(void (*clock)(void))


@@ 68,15 70,35 @@ clockinit(void)
	if(m->delayloop == 0)
		m->delayloop = 1;

	wrcompare(rdcount()+(m->speed*1000000)/HZ);
	incr = (m->speed*1000000)/HZ;
	fasthz = m->speed*1000000;
	wrcompare(rdcount()+incr);
}

uvlong
updatefastclock(ulong count)
{
	uvlong cyclecount;

	/* keep track of higher precision time */
	cyclecount = count;
	if(cyclecount < m->lastcyclecount)
		m->fastclock += (0x100000000LL - m->lastcyclecount) + cyclecount;
	else
		m->fastclock += cyclecount - m->lastcyclecount;
	m->lastcyclecount = cyclecount;
	return m->fastclock;
}

void
clock(Ureg *ur)
{
	Clock0link *lp;
	ulong count;

	wrcompare(rdcount()+(m->speed*1000000)/HZ);
	count = rdcount();
	wrcompare(count+incr);
	updatefastclock(count);

	m->ticks++;
	if(m->proc)


@@ 127,7 149,15 @@ clock(Ureg *ur)
vlong
fastticks(uvlong *hz)
{
	uvlong cyclecount;
	int x;

	x = splhi();
	cyclecount = updatefastclock(rdcount());
	splx(x);

	if(hz)
		*hz = HZ*100;
	return (vlong)m->ticks*100;
		*hz = fasthz;

	return (vlong)cyclecount;
}

M carrera/dat.h => carrera/dat.h +2 -1
@@ 115,7 115,8 @@ struct Mach
	ulong	delayloop;		/* for the delay() routine */
	int	nrdy;
	ulong	fairness;		/* for runproc */
	vlong	fastclock;		/* last sampled value */
	ulong	lastcyclecount;
	uvlong	fastclock;
	int	flushmmu;		/* make current proc flush it's mmu state */

	int	pfault;

M pc/clock.c => pc/clock.c +13 -0
@@ 95,3 95,16 @@ microdelay(int microsecs)
		microsecs = 1;
	aamloop(microsecs);
}

ulong
TK2MS(ulong ticks)
{
	uvlong t, hz;

	t = ticks;
	hz = HZ;
	t *= 1000L;
	t = t/hz;
	ticks = t;
	return ticks;
}

M pc/i8259.c => pc/i8259.c +23 -22
@@ 25,10 25,9 @@ enum
	Elcr2=		0x4D1,
};

static int int0mask;			/* interrupts enabled for first 8259 */
static int int1mask;			/* interrupts enabled for second 8259 */
int elcr;				/* mask of level-triggered interrupts */
static Lock i8259lock;
static int i8259mask = 0xFFFF;		/* disabled interrupts */
int i8259elcr;				/* mask of level-triggered interrupts */

void
i8259init(void)


@@ 36,8 35,6 @@ i8259init(void)
	int x;

	ilock(&i8259lock);
	int0mask = 0xFF;
	int1mask = 0xFF;

	/*
	 *  Set up the first 8259 interrupt processor.


@@ 62,13 59,13 @@ i8259init(void)
	outb(Int1aux, VectorPIC+8);		/* ICW2 - interrupt vector offset */
	outb(Int1aux, 0x02);			/* ICW3 - I am a slave on level 2 */
	outb(Int1aux, 0x01);			/* ICW4 - 8086 mode, not buffered */
	outb(Int1aux, int1mask);
	outb(Int1aux, (i8259mask>>8) & 0xFF);

	/*
	 *  pass #2 8259 interrupts to #1
	 */
	int0mask &= ~0x04;
	outb(Int0aux, int0mask);
	i8259mask &= ~0x04;
	outb(Int0aux, i8259mask & 0xFF);

	/*
	 * Set Ocw3 to return the ISR when ctl read.


@@ 94,9 91,9 @@ i8259init(void)
		if(inb(Elcr1) == 0){
			outb(Elcr1, 0x20);
			if(inb(Elcr1) == 0x20)
				elcr = x;
				i8259elcr = x;
			outb(Elcr1, x & 0xFF);
			//print("ELCR: %4.4uX\n", elcr);
			//print("ELCR: %4.4uX\n", i8259elcr);
		}
	}
	iunlock(&i8259lock);


@@ 105,10 102,11 @@ i8259init(void)
int
i8259isr(int vno)
{
	int isr;
	int irq, isr;

	if(vno < VectorPIC || vno > VectorPIC+MaxIrqPIC)
		return 0;
	irq = vno-VectorPIC;

	/*
	 *  tell the 8259 that we're done with the


@@ 118,19 116,19 @@ i8259isr(int vno)
	ilock(&i8259lock);
	isr = inb(Int0ctl);
	outb(Int0ctl, EOI);
	if(vno >= VectorPIC+8){
	if(irq >= 8){
		isr |= inb(Int1ctl)<<8;
		outb(Int1ctl, EOI);
	}
	iunlock(&i8259lock);

	return isr & (1<<(vno-VectorPIC));
	return isr & (1<<irq);
}

int
i8259enable(Vctl* v)
{
	int irq;
	int irq, irqbit;

	/*
	 * Given an IRQ, enable the corresponding interrupt in the i8259


@@ 142,18 140,21 @@ i8259enable(Vctl* v)
		print("i8259enable: irq %d out of range\n", irq);
		return -1;
	}
	irqbit = 1<<irq;

	ilock(&i8259lock);
	if(irq < 8){
		int0mask &= ~(1<<irq);
		outb(Int0aux, int0mask);
	}
	else{
		int1mask &= ~(1<<(irq-8));
		outb(Int1aux, int1mask);
	if(!(i8259mask & irqbit) && !(i8259elcr & irqbit)){
		print("i8259enable: irq %d shared but not level\n", irq);
		iunlock(&i8259lock);
		return -1;
	}
	i8259mask &= ~irqbit;
	if(irq < 8)
		outb(Int0aux, i8259mask & 0xFF);
	else
		outb(Int1aux, (i8259mask>>8) & 0xFF);

	if(elcr & (1<<irq))
	if(i8259elcr & irqbit)
		v->eoi = i8259isr;
	else
		v->isr = i8259isr;

M pc/io.h => pc/io.h +5 -3
@@ 144,7 144,8 @@ enum {					/* type 1 pre-defined header */
};

typedef struct Pcidev Pcidev;
typedef struct Pcidev {
struct Pcidev
{
	int	tbdf;			/* type+bus+device+function */
	ushort	vid;			/* vendor ID */
	ushort	did;			/* device ID */


@@ 155,8 156,9 @@ typedef struct Pcidev {
	} mem[6];

	uchar	intl;			/* interrupt line */
	ushort	ccru;

	uchar	ccrp;
	uchar	ccru;
	uchar	ccrb;

	Pcidev*	list;
	Pcidev*	bridge;			/* down a bus */

M pc/mp.c => pc/mp.c +1 -1
@@ 13,7 13,7 @@ static Bus* mpbus;
static Bus* mpbuslast;
static int mpisabus = -1;
static int mpeisabus = -1;
extern int elcr;			/* mask of level-triggered interrupts */
extern int i8259elcr;			/* mask of level-triggered interrupts */
static Apic mpapic[MaxAPICNO+1];
static int machno2apicno[MaxAPICNO+1];	/* inverse map: machno -> APIC ID */
static Lock mprdthilock;

M pc/pci.c => pc/pci.c +277 -66
@@ 1,7 1,5 @@
/*
 * PCI support code.
 * To do:
 *	initialise bridge mappings if the PCI BIOS didn't.
 */
#include "u.h"
#include "../port/lib.h"


@@ 11,7 9,8 @@
#include "io.h"
#include "../port/error.h"

enum {					/* configuration mechanism #1 */
enum
{					/* configuration mechanism #1 */
	PciADDR		= 0xCF8,	/* CONFIG_ADDRESS */
	PciDATA		= 0xCFC,	/* CONFIG_DATA */



@@ 21,6 20,20 @@ enum {					/* configuration mechanism #1 */

	MaxFNO		= 7,
	MaxUBN		= 255,

	BARio		= 0,		/* fake BAR registers for bridges */
	BARmem,

	NOBIOS		= 0,		/* initialise if the BIOS didn't */
};

enum {					/* command register */
	IOen		= (1<<0),
	MEMen		= (1<<1),
	MASen		= (1<<2),
	MemWrInv	= (1<<4),
	PErrEn		= (1<<6),
	SErrEn		= (1<<8),
};

static Lock pcicfglock;


@@ 32,11 45,150 @@ static Pcidev* pcilist;
static Pcidev* pcitail;

static int pcicfgrw32(int, int, int, int);
static int pcicfgrw8(int, int, int, int);

ulong
pcibarsize(Pcidev *p, int rno)
{
	ulong v, size;

	v = pcicfgrw32(p->tbdf, rno, 0, 1);
	pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
	size = pcicfgrw32(p->tbdf, rno, 0, 1);
	if(v & 1)
		size |= 0xFFFF0000;
	pcicfgrw32(p->tbdf, rno, v, 0);

	return -(size & ~0x0F);
}

static void
pcibusmap(Pcidev *p, ulong *pmema, ulong *pioa, int wrreg)
{
	int i, size, k;
	ulong addr, v, mema, ioa, pcr, tmema, tioa;

	if(!NOBIOS)
		return;

	mema = *pmema;
	ioa = *pioa;

	print("pcibusmap wr=%d %d.%d.%d mem=%lux io=%lux\n", 
		wrreg, BUSBNO(p->tbdf), BUSDNO(p->tbdf), BUSFNO(p->tbdf),
		mema, ioa);

	/*
	 * Allocate address space on this bus
	 * note this loop follows link, not list
	 */
	for(; p; p = p->link) {
		if(p->ccrb == 0x06) {
			if(p->ccru != 0x04) {
				print("pci: ignored bridge %d.%d.%d\n",
					BUSBNO(p->tbdf),
					BUSDNO(p->tbdf),
					BUSFNO(p->tbdf));
				continue;
			}

			/* Base */
			p->mem[BARio].bar = ioa;
			p->mem[BARmem].bar = mema;
			tioa = ioa;
			tmema = mema;

			/* Limit */
			ioa += p->mem[BARio].size;
			mema += p->mem[BARmem].size;

			if(wrreg == 0)
				continue;

			pcibusmap(p->bridge, &tmema, &tioa, 1);

			/*
			 * IO base[15:12], IO limit [15:12]
			 */
			v =	(0xFFFF<<16)|
				(ioa & 0xF000)|
				((p->mem[BARio].bar & 0xF000)>>8);

			pcicfgrw32(p->tbdf, PciBAR3, v, 0);

			/*
			 * Memory Base/Limit
			 */
			v =	(mema & ~((1<<20)-1)) |
				((p->mem[BARmem].bar & ~((1<<20)-1)) >> 16);

			pcicfgrw32(p->tbdf, PciBAR4, v, 0);

			/*
			 * Disable memory prefetch
			 */
			pcicfgrw32(p->tbdf, PciBAR5, 0x0000FFFF, 0);

			/*
			 * Enable the bridge
			 */
			v = 0xFFFF0000 | IOen | MEMen | MASen;
			pcicfgrw32(p->tbdf, PciPCR, v, 0);
			continue;
		}

		pcr = pcicfgrw32(p->tbdf, PciPCR, 0, 1);
		
		for(i = PciBAR0; i <= PciBAR5; i += 4) {
			v = pcicfgrw32(p->tbdf, i, 0, 1);
			size = pcibarsize(p, i);
			if(size > 16*1024*1024)
				print("pcimap: size %d?\n", size);
			if(size == 0)
				continue;

			if(v & 1) {		/* Allocate IO space */
				ioa = (ioa+size-1) & ~(size-1);
				addr = ioa;
				ioa += size;
				pcr |= IOen;
			}
			else {			/* Allocate Memory space */
				mema = (mema+size-1) & ~(size-1);
				addr = mema;
				mema += size;
				pcr |= MEMen;
			}

			k = (i-PciBAR0)/4;
			p->mem[k].size = size;
			p->mem[k].bar = addr;
			if(wrreg)
				pcicfgrw32(p->tbdf, i, addr, 0);
		}

		/*
		 * Set latency timer
		 * Enable memory/io/master
		 */
		if(wrreg) {
			pcicfgrw8(p->tbdf, PciLTR, 64, 0);

			pcr |= MASen;
			pcicfgrw32(p->tbdf, PciPCR, pcr, 0);
		}
	}

	print("pcibusmap mem=%lux io=%lux\n", mema, ioa);

	*pmema = mema;
	*pioa = ioa;
}

static int
pciscan(int bno, Pcidev** list)
{
	ulong v;
	ulong mema, ioa;
	Pcidev *p, *head, *tail;
	int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;



@@ 47,11 199,12 @@ pciscan(int bno, Pcidev** list)
		maxfno = 0;
		for(fno = 0; fno <= maxfno; fno++){
			/*
			 * For this possible device, form the bus+device+function
			 * triplet needed to address it and try to read the vendor
			 * and device ID. If successful, allocate a device struct
			 * and start to fill it in with some useful information from
			 * the device's configuration space.
			 * For this possible device, form the
			 * bus+device+function triplet needed to address it
			 * and try to read the vendor and device ID.
			 * If successful, allocate a device struct and
			 * start to fill it in with some useful information
			 * from the device's configuration space.
			 */
			tbdf = MKBUS(BusPCI, bno, dno, fno);
			l = pcicfgrw32(tbdf, PciVID, 0, 1);


@@ 69,7 222,9 @@ pciscan(int bno, Pcidev** list)
			pcitail = p;

			p->intl = pcicfgr8(p, PciINTL);
			p->ccru = pcicfgr16(p, PciCCRu);
			p->ccrp = pcicfgr8(p, PciCCRp);
			p->ccru = pcicfgr8(p, PciCCRu);
			p->ccrb = pcicfgr8(p, PciCCRb);

			/*
			 * If the device is a multi-function device adjust the


@@ 83,13 238,12 @@ pciscan(int bno, Pcidev** list)
			 * If appropriate, read the base address registers
			 * and work out the sizes.
			 */
			switch(p->ccru>>8){

			switch(p->ccrb) {
			case 0x01:		/* mass storage controller */
			case 0x02:		/* network controller */
			case 0x03:		/* display controller */
			case 0x04:		/* multimedia device */
			case 0x07:		/* simple communication controllers */
			case 0x07:		/* simple comm. controllers */
			case 0x08:		/* base system peripherals */
			case 0x09:		/* input devices */
			case 0x0A:		/* docking stations */


@@ 98,13 252,10 @@ pciscan(int bno, Pcidev** list)
				if((hdt & 0x7F) != 0)
					break;
				rno = PciBAR0 - 4;
				for(i = 0; i < nelem(p->mem); i++){
				for(i = 0; i < nelem(p->mem); i++) {
					rno += 4;
					p->mem[i].bar = pcicfgr32(p, rno);
					pcicfgw32(p, rno, -1);
					v = pcicfgr32(p, rno);
					pcicfgw32(p, rno, p->mem[i].bar);
					p->mem[i].size = -(v & ~0xF);
					p->mem[i].size = pcibarsize(p, rno);
				}
				break;



@@ 128,26 279,27 @@ pciscan(int bno, Pcidev** list)
		/*
		 * Find PCI-PCI bridges and recursively descend the tree.
		 */
		if(p->ccru != ((0x06<<8)|0x04))
		if(p->ccrb != 0x06 || p->ccru != 0x04)
			continue;

		/*
		 * If the secondary or subordinate bus number is not initialised
		 * try to do what the PCI BIOS should have done and fill in the
		 * numbers as the tree is descended. On the way down the subordinate
		 * bus number is set to the maximum as it's not known how many
		 * buses are behind this one; the final value is set on the way
		 * back up.
		 * If the secondary or subordinate bus number is not
		 * initialised try to do what the PCI BIOS should have
		 * done and fill in the numbers as the tree is descended.
		 * On the way down the subordinate bus number is set to
		 * the maximum as it's not known how many buses are behind
		 * this one; the final value is set on the way back up.
		 */
		sbn = pcicfgr8(p, PciSBN);
		ubn = pcicfgr8(p, PciUBN);
		if(sbn == 0 || ubn == 0){

		if(sbn == 0 || ubn == 0 || NOBIOS) {
			sbn = maxubn+1;
			/*
			 * Make sure memory, I/O and master enables are off,
			 * set the primary, secondary and subordinate bus numbers
			 * and clear the secondary status before attempting to
			 * scan the secondary bus.
			 * Make sure memory, I/O and master enables are
			 * off, set the primary, secondary and subordinate
			 * bus numbers and clear the secondary status before
			 * attempting to scan the secondary bus.
			 *
			 * Initialisation of the bridge should be done here.
			 */


@@ 157,60 309,118 @@ pciscan(int bno, Pcidev** list)
			pcicfgw16(p, PciSPSR, 0xFFFF);
			maxubn = pciscan(sbn, &p->bridge);
			l = (maxubn<<16)|(sbn<<8)|bno;

			pcicfgw32(p, PciPBN, l);
		}
		else{
		else {
			maxubn = ubn;
			pciscan(sbn, &p->bridge);
		}

		/*
		 * Now figure out the size of things below the bridge
		 */
		if(NOBIOS) {
			mema = 0;
			ioa = 0;
			pcibusmap(p->bridge, &mema, &ioa, 0);
			p->mem[BARmem].size = ROUND(mema, 1<<20);
			p->mem[BARio].size = ROUND(ioa, 1<<12);
		}
	}

	return maxubn;
}

static ulong
pcimask(ulong v)
{
	ulong m;

	if(!NOBIOS)
		return 0;

	m = BI2BY*sizeof(v);
	for(m = 1<<(m-1); m != 0; m >>= 1) {
		if(m & v)
			break;
	}
	v |= m-1;
	return v+1;
}

static void
pcicfginit(void)
{
	char *p;
	int bno;
	Pcidev **list;
	ulong mema, ioa, size;

	lock(&pcicfginitlock);
	if(pcicfgmode == -1){
	if(pcicfgmode != -1)
		goto out;

	/*
	 * Try to determine which PCI configuration mode is implemented.
	 * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
	 * a DWORD at 0xCF8 and another at 0xCFC and will pass through
	 * any non-DWORD accesses as normal I/O cycles. There shouldn't be
	 * a device behind these addresses so if Mode2 accesses fail try
	 * for Mode1 (which is preferred, Mode2 is deprecated).
	 */
	outb(PciCSE, 0);
	if(inb(PciCSE) == 0){
		pcicfgmode = 2;
		pcimaxdno = 15;
	}
	else {
		outl(PciADDR, 0);
		if(inl(PciADDR) == 0){
			pcicfgmode = 1;
			pcimaxdno = 31;
		}
	}
	
	if(pcicfgmode < 0)
		goto out;

	if(p = getconf("*pcimaxdno"))
		pcimaxdno = strtoul(p, 0, 0);

	list = &pciroot;
	for(bno = 0; bno < 256; bno++) {
		bno = pciscan(bno, list);
		while(*list)
			list = &(*list)->link;
	}

	if(NOBIOS){
		/*
		 * Try to determine which PCI configuration mode is implemented.
		 * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
		 * a DWORD at 0xCF8 and another at 0xCFC and will pass through
		 * any non-DWORD accesses as normal I/O cycles. There shouldn't be
		 * a device behind these addresses so if Mode2 accesses fail try
		 * for Mode1 (which is preferred, Mode2 is deprecated).
		 * Work out how big the top bus is
		 */
		outb(PciCSE, 0);
		if(inb(PciCSE) == 0){
			pcicfgmode = 2;
			pcimaxdno = 15;
		}
		else{
			outl(PciADDR, 0);
			if(inl(PciADDR) == 0){
				pcicfgmode = 1;
				pcimaxdno = 31;
			}
		}
		mema = 0;
		ioa = 0;
		pcibusmap(pciroot, &mema, &ioa, 0);
	
		if(pcicfgmode > 0){
			if(p = getconf("*pcimaxdno"))
				pcimaxdno = strtoul(p, 0, 0);

			list = &pciroot;
			for(bno = 0; bno < 256; bno++){
				bno = pciscan(bno, list);
				while(*list)
					list = &(*list)->link;
			}
				
		}
		print("Sizes: mem=%lux io=%lux\n", mema, ioa);
	
		/*
		 * Align the windows and map it
		 */
		size = pcimask(mema);
		mema = (0xFE000000 & ~(size-1)) - size;
		size = pcimask(ioa);
		ioa = (0xFE00 & ~(size-1)) - size;
	
		pcibusmap(pciroot, &mema, &ioa, 1);
	
		unlock(&pcicfginitlock);
		pcihinv(nil);

		return;
	}
out:
	unlock(&pcicfginitlock);
}



@@ 396,7 606,8 @@ pcimatch(Pcidev* prev, int vid, int did)
		prev = prev->list;

	while(prev != nil){
		if((vid == 0 || prev->vid == vid) && (did == 0 || prev->did == did))
		if((vid == 0 || prev->vid == vid)
		&& (did == 0 || prev->did == did))
			break;
		prev = prev->list;
	}


@@ 411,7 622,7 @@ pcimatchtbdf(int tbdf)
	if(pcicfgmode == -1)
		pcicfginit();

	for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list){
	for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
		if(pcidev->tbdf == tbdf)
			break;
	}


@@ 429,9 640,9 @@ pcihinv(Pcidev* p)
		print("bus dev type vid  did intl memory\n");
	}
	for(t = p; t != nil; t = t->link) {
		print("%d  %2d/%d %.4ux %.4ux %.4ux %2d  ",
		print("%d  %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %2d  ",
			BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
			t->ccru, t->vid, t->did, t->intl);
			t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);

		for(i = 0; i < nelem(p->mem); i++) {
			if(t->mem[i].size == 0)

M pc/pcmciamodem.c => pc/pcmciamodem.c +1 -1
@@ 54,7 54,7 @@ pcmciamodemlink(void)
		for(j = 0; modems[j]; j++){
			slot = pcmspecial(modems[j], &isa);
			if(slot >= 0){
				print("%s in pcmcia slot %d port 0x%lx irq %d\n",
				print("%s in pcmcia slot %d port 0x%lux irq %lud\n",
					modems[j], slot, isa.port, isa.irq);
				break;
			}

M pc/scsi.c => pc/scsi.c +6 -113
@@ 13,8 13,6 @@ enum {

	CMDtest		= 0x00,
	CMDreqsense	= 0x03,
	CMDread6	= 0x08,
	CMDwrite6	= 0x0A,
	CMDinquire	= 0x12,
	CMDstart	= 0x1B,
	CMDcapacity	= 0x25,


@@ 361,7 359,12 @@ scsireqsense(Target *t, char lun, void *data, int *nbytes, int quiet)
		switch(sense[2] & 0x0F){

		case 6:					/* unit attention */
			if(sense[12] != 0x29)		/* power on, reset */
			/*
			 * 0x28 - not ready to ready transition,
			 *	  medium may have changed.
			 * 0x29 - power on, RESET or BUS DEVICE RESET occurred.
			 */
			if(sense[12] != 0x28 && sense[12] != 0x29)
				goto buggery;
			/*FALLTHROUGH*/
		case 0:					/* no sense */


@@ 408,116 411,6 @@ buggery:
	return STcheck;
}

int
scsidiskinfo(Target *t, char lun, int track, uchar *data)
{
	int s, nbytes;
	uchar cmd[10], *d;

	nbytes = 12;

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x43;
	cmd[1] = lun<<5;
	cmd[6] = track;
	cmd[7] = nbytes>>8;
	cmd[8] = nbytes;

	d = scsialloc(nbytes);
	if(d == 0)
		return scsierrstr(STnomem);

	memset(d, 0, nbytes);
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes);
	memmove(data, d, 12);
	scsifree(d);
	return s;
}

int
scsitrackinfo(Target *t, char lun, int track, uchar *data)
{
	int s, nbytes;
	uchar cmd[10], *d;

	nbytes = 12;

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0xe5;
	cmd[1] = lun<<5;
	cmd[5] = track;
	cmd[7] = nbytes>>8;
	cmd[8] = nbytes;

	d = scsialloc(nbytes);
	if(d == 0)
		return scsierrstr(STnomem);

	memset(d, 0, nbytes);
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes);
	memmove(data, d, 12);
	scsifree(d);

	return s;
}

int
scsibufsize(Target *t, char lun, int size)
{
	int s, nbytes;
	uchar cmd[6], *d;

	nbytes = 12;

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x15;
	cmd[1] = lun<<5;
	cmd[4] = nbytes;

	d = scsialloc(nbytes);
	if(d == 0)
		return scsierrstr(STnomem);

	memset(d, 0, nbytes);
	d[3] = 8;
	d[8] = size>>24;
	d[9] = size>>16;
	d[10] = size>>8;
	d[11] = size;

	s = scsiexec(t, SCSIwrite, cmd, sizeof(cmd), d, &nbytes);
	scsifree(d);
	return s;
}

int
scsireadcdda(Target *t, char lun, int, void *b, long n, long bsize, long bno)
{
	uchar cmd[12];
	int s, nbytes;

	memset(cmd, 0, sizeof(cmd));

	cmd[0] = 0xd8;
	cmd[1] = (lun<<5);
	cmd[2] = bno>>24;
	cmd[3] = bno>>16;
	cmd[4] = bno>>8;
	cmd[5] = bno;
	cmd[6] = n>>24;
	cmd[7] = n>>16;
	cmd[8] = n>>8;
	cmd[9] = n;

	nbytes = n*bsize;
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), b, &nbytes);
	if(s != STok) {
		nbytes = Nscratch;
		scsireqsense(t, lun, t->scratch, &nbytes, 0);
		return scsierrstr(s);
	}
	return nbytes;
}

int
scsierrstr(int errno)

M pc/trap.c => pc/trap.c +32 -23
@@ 30,16 30,16 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf)

	ilock(&vctllock);
	vno = arch->intrenable(v);
	//print("irq%d, vno %d\n", irq, vno);
	if(vno == -1){
		iunlock(&vctllock);
		print("intrenable: couldn't enable irq %d, tbdf 0x%uX\n", irq, tbdf);
		print("intrenable: couldn't enable irq %d, tbdf 0x%uX\n",
			irq, tbdf);
		xfree(v);
		return;
	}
	if(vctl[vno]){
		if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
			panic("intrenable: irq handler botch: %luX %luX %luX %luX\n",
			panic("intrenable: handler: %luX %luX %luX %luX\n",
				vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
		v->next = vctl[vno];
	}


@@ 158,9 158,10 @@ static char* excname[32] = {
};

/*
 *  All traps come here.  It is slower to have all traps call trap() rather than
 *  directly vectoring the handler.  However, this avoids a lot of code duplication
 *  and possible bugs.  The only exception is VectorSYSCALL.
 *  All traps come here.  It is slower to have all traps call trap()
 *  rather than directly vectoring the handler.  However, this avoids a
 *  lot of code duplication and possible bugs.  The only exception is
 *  VectorSYSCALL.
 *  Trap is called with interrupts disabled via interrupt-gates.
 */
void


@@ 244,7 245,8 @@ trap(Ureg* ureg)
		if(vno == VectorNMI){
			nmienable();
			if(m->machno != 0){
				print("cpu%d: PC %8.8luX\n", m->machno, ureg->pc);
				print("cpu%d: PC %8.8luX\n",
					m->machno, ureg->pc);
				for(;;);
			}
		}


@@ 267,11 269,12 @@ void
dumpregs2(Ureg* ureg)
{
	if(up)
		print("cpu%d: registers for %s %lud\n", m->machno, up->text, up->pid);
		print("cpu%d: registers for %s %lud\n",
			m->machno, up->text, up->pid);
	else
		print("cpu%d: registers for kernel\n", m->machno);
	print("FLAGS=%luX TRAP=%luX ECODE=%luX PC=%luX", ureg->flags, ureg->trap,
		ureg->ecode, ureg->pc);
	print("FLAGS=%luX TRAP=%luX ECODE=%luX PC=%luX",
		ureg->flags, ureg->trap, ureg->ecode, ureg->pc);
	print(" SS=%4.4luX USP=%luX\n", ureg->ss & 0xFFFF, ureg->usp);
	print("  AX %8.8luX  BX %8.8luX  CX %8.8luX  DX %8.8luX\n",
		ureg->ax, ureg->bx, ureg->cx, ureg->dx);


@@ 292,12 295,13 @@ dumpregs(Ureg* ureg)

	/*
	 * Processor control registers.
	 * If machine check exception, time stamp counter, page size extensions or
	 * enhanced virtual 8086 mode extensions are supported, there is a CR4.
	 * If there is a CR4 and machine check extensions, read the machine check
	 * address and machine check type registers if RDMSR supported.
	 * If machine check exception, time stamp counter, page size extensions
	 * or enhanced virtual 8086 mode extensions are supported, there is a
	 * CR4. If there is a CR4 and machine check extensions, read the machine
	 * check address and machine check type registers if RDMSR supported.
	 */
	print("  CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux", getcr0(), getcr2(), getcr3());
	print("  CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux",
		getcr0(), getcr2(), getcr3());
	if(m->cpuiddx & 0x9A){
		print(" CR4 %8.8lux", getcr4());
		if((m->cpuiddx & 0xA0) == 0xA0){


@@ 328,7 332,8 @@ dumpstack(void)
			 * through AX (0xFFD0).
			 */
			p = (uchar*)v;
			if(*(p-5) == 0xE8 || (*(p-2) == 0xFF && *(p-1) == 0xD0)){
			if(*(p-5) == 0xE8
			|| (*(p-2) == 0xFF && *(p-1) == 0xD0)){
				print("%lux ", p-5);
				i++;
			}


@@ 417,7 422,8 @@ syscall(Ureg* ureg)
	ret = -1;
	if(!waserror()){
		if(scallnr >= nsyscall){
			pprint("bad sys call number %d pc %lux\n", scallnr, ureg->pc);
			pprint("bad sys call number %d pc %lux\n",
				scallnr, ureg->pc);
			postnote(up, 1, "sys: bad sys call", NDebug);
			error(Ebadarg);
		}


@@ 434,7 440,8 @@ syscall(Ureg* ureg)
	if(up->nerrlab){
		print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
		for(i = 0; i < NERR; i++)
			print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
			print("sp=%lux pc=%lux\n",
				up->errlab[i].sp, up->errlab[i].pc);
		panic("error stack");
	}



@@ 551,7 558,7 @@ noted(Ureg* ureg, ulong arg0)
	}
	up->notified = 0;

	nureg = up->ureg;		/* pointer to user returned Ureg struct */
	nureg = up->ureg;	/* pointer to user returned Ureg struct */

	/* sanity clause */
	oureg = (ulong)nureg;


@@ 594,7 601,8 @@ noted(Ureg* ureg, ulong arg0)
		break;

	case NSAVE:
		if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->usp, BY2WD, 0)){
		if(!okaddr(nureg->pc, BY2WD, 0)
		|| !okaddr(nureg->usp, BY2WD, 0)){
			pprint("suicide: trap in noted\n");
			qunlock(&up->debug);
			pexit("Suicide", 0);


@@ 644,8 652,8 @@ userpc(void)
	return ureg->pc;
}

/* This routine must save the values of registers the user is not permitted to write
 * from devproc and then restore the saved values before returning
/* This routine must save the values of registers the user is not permitted
 * to write from devproc and then restore the saved values before returning.
 */
void
setregisters(Ureg* ureg, char* pureg, char* uva, int n)


@@ 695,7 703,8 @@ forkchild(Proc *p, Ureg *ureg)

	cureg = (Ureg*)(p->sched.sp+2*BY2WD);
	memmove(cureg, ureg, sizeof(Ureg));
	cureg->ax = 0;				/* return value of syscall in child */
	/* return value of syscall in child */
	cureg->ax = 0;

	/* Things from bottom of syscall which were never executed */
	p->psstate = 0;