Revision: 411c2e37f2
Author: Mechiel Lukkien <mec...@ueber.net>
Date: Wed Aug 25 14:23:25 2010
Log: print a message on prefetch & data abort.
http://code.google.com/p/inferno-kirkwood/source/detail?r=411c2e37f2
Revision: 57863205ca
Author: Mechiel Lukkien <mec...@ueber.net>
Date: Wed Aug 25 14:32:43 2010
Log: update readme (updated todo list, better instructions)
http://code.google.com/p/inferno-kirkwood/source/detail?r=57863205ca
Revision: fe369a32a6
Author: Mechiel Lukkien <mec...@ueber.net>
Date: Wed Aug 25 14:36:10 2010
Log: improvements to sata....
http://code.google.com/p/inferno-kirkwood/source/detail?r=fe369a32a6
==============================================================================
Revision: 411c2e37f2
Author: Mechiel Lukkien <mec...@ueber.net>
Date: Wed Aug 25 14:23:25 2010
Log: print a message on prefetch & data abort.
http://code.google.com/p/inferno-kirkwood/source/detail?r=411c2e37f2
Modified:
/trap.c
=======================================
--- /trap.c Mon Mar 15 06:57:05 2010
+++ /trap.c Wed Aug 25 14:23:25 2010
@@ -331,13 +331,14 @@
break;
case PsrMabt: /* Prefetch abort */
+ iprint("trap:prefetch abort\n");
if(catchdbg && catchdbg(ureg, 0))
break;
/* FALL THROUGH */
case PsrMabt+1: /* Data abort */
-/* xxx we don't do mmu, remove this? */
+ iprint("trap:data abort");
/*
- ulong far, fsr;
+ ulong far, fsr;
fsr = mmugetfsr();
far = mmugetfar();
if(fsr & (1<<9)) {
@@ -415,7 +416,7 @@
void
_dumpstack(Ureg*)
{
- print("dumpstack\n");
+ print("_dumpstack\n");
}
void
@@ -440,7 +441,6 @@
print("R4 %8.8uX R3 %8.8uX R2 %8.8uX R1 %8.8uX R0 %8.8uX\n",
ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
print("Stack is at: %8.8luX\n", ureg);
- print("PC %8.8lux LINK %8.8lux\n", (ulong)ureg->pc, (ulong)ureg->link);
if(up)
print("Process stack: %8.8lux-%8.8lux\n",
==============================================================================
Revision: 57863205ca
Author: Mechiel Lukkien <mec...@ueber.net>
Date: Wed Aug 25 14:32:43 2010
Log: update readme (updated todo list, better instructions)
http://code.google.com/p/inferno-kirkwood/source/detail?r=57863205ca
Modified:
/README
=======================================
--- /README Tue Mar 30 09:26:40 2010
+++ /README Wed Aug 25 14:32:43 2010
@@ -4,10 +4,11 @@
support (dhcp & mount working), might read some sd cards, can read
nand flash pages.
-next steps:
+todo:
+- writing kernels to nand (can be done from u-boot, also should be
possible from userland): will implement raw flash device, like flash(3)
but with oob data to be read/written too. then implement a program to
write an image (that executes erase and such).
+- better nand support
- find & fix crash with latest uboot
- l2 cache, does not seem to speed up much. something wrong?
-- better nand support
- delay/microdelay calibration
- better sata support
- perform register file read after register writes to different registers
@@ -48,10 +49,9 @@
# booting
-we can only boot from tftp for now. set up a dhcp & tftp server.
-the dhcp server should have a boot file name (the kernel, e.g.
-uisheeva.gz) and a next server (the ip address of the tftp server)
-configured.
+for development it is easiest to boot from dhcp/tftp. the dhcp
+server should have a boot file name (the kernel, e.g. uisheeva.gz)
+and a "next server" (the ip address of the tftp server) configured.
after reset, hit some keys to prevent u-boot from auto-booting.
the following commands boot inferno:
@@ -60,16 +60,32 @@
tftp # fetch kernel
bootm # boot the kernel
-inferno boots into a shell. a few commands are available. for
-development, mdb is useful for reading/writing registers, e.g.:
-
- mdb -w /dev/sheevaregs
-
-to make mdb do anything useful with the sheevaplugs registers (which
-are configured at 0xf1000000, high bit set), you'll need to apply
-the patch misc/mdb.b.diff.
-
-to configure network with dhcp, and provide shells on the telnet port:
+the default boot command can be set like so:
+
+ setenv bootcmd 'dhcp; tftp; bootm'
+ saveenv
+
+booting from nand flash is also possible. the first 1mb of nand
+is used for u-boot. we'll use the linux convention of the 4mb after
+that for the kernel and the remainder of the memory for the file
+system. u-boot has commands to write to flash memory. the kernel
+should be in RAM at that point (which you can do by reading from
+the network, SD card, etc.). for example:
+
+ bootp
+ tftp # fetches kernel from network, places it at 0x2000000 in my u-boot
+ nand erase 0x00100000 0x00400000 # erase 4mbyte, starting at 1mbyte
offset
+ nand write.e 0x2000000 0x00100000 0x00400000 # write kernel from RAM
(where tftp put it) to nand at 1mbyte offset. this writes 4m.
+ # .e skips bad blocks. it
is probably wise to write only the size of the kernel to flash.
+
+to boot this flash kernel:
+
+ nand read.e 0x2000000 0x00100000 0x00400000
+ bootm 0x2000000
+
+
+once booted, to configure network with dhcp, and provide shells on
+the telnet port:
run /netrc
==============================================================================
Revision: fe369a32a6
Author: Mechiel Lukkien <mec...@ueber.net>
Date: Wed Aug 25 14:36:10 2010
Log: improvements to sata.
still nowhere near finished, but at least we can initialise a sata
disk without help from u-boot. afterwards we can still read/write
data to disk.
the registers in io.h have been changed to better reflect whether
the regs are for edma, bdma or the sata interface.
debug printing can be enabled/disabled now by writing "debug <num>"
to #S/sd01/ctl.
writing "reset" to #S/sd01/ctl resets the port and reinitialises
the disk.
still lots missing, see the top of devsata.c for a list.
http://code.google.com/p/inferno-kirkwood/source/detail?r=fe369a32a6
Modified:
/archkirkwood.c
/devsata.c
/io.h
=======================================
--- /archkirkwood.c Wed Mar 17 05:01:18 2010
+++ /archkirkwood.c Wed Aug 25 14:36:10 2010
@@ -134,7 +134,7 @@
TIMERREG->ctl &= ~TmrWDenable;
/* physhutdown first port to save power, sheevaplug esata uses second
port. */
- SATA0REG->ifccfg |= 1<<9;
+ SATA0REG->ifc.ifccfg |= 1<<9;
/* configure gpios */
// GPIO0REG->dataout = UsbPWOEValLow;
=======================================
--- /devsata.c Wed Mar 17 16:39:56 2010
+++ /devsata.c Wed Aug 25 14:36:10 2010
@@ -4,17 +4,18 @@
for now we'll assume ncq "first party dma" read/write commands (very old
sata disks won't work).
todo:
+- properly wait until device is no longer busy during startup
- proper locking, wait for free edma slot.
- look at cache flushes around dma
- error handling & propagating to caller.
-- phy errata
- better detect ata support of drives
- interrupt coalescing
- fix ncq, return early responses (in different order than request queue)
- general ata commands
- use generic sd interface (#S; we need partitions)
-- hotplug
-- abstract for multiple ports
+- hotplug, at least handle disconnects
+- abstract for multiple ports (add controller struct to functions)
+- in satainit(), only start the disk init, don't wait for it to be ready?
faster booting, seems it takes controller/disk some time to init after
reset.
- support for non-ncq drives, by normal dma commands?
- for large i/o requests, could have always two ops scheduled: less
waiting, still no hogging.
*/
@@ -28,7 +29,9 @@
#include "io.h"
-#define diprint if(0)iprint
+static int satadebug = 1;
+#define diprint if(satadebug)iprint
+#define dprint if(satadebug)print
char Enodisk[] = "no disk";
@@ -120,7 +123,7 @@
/* edma command */
EdmaEnable = 1<<0, /* enable edma */
- EdmaDisable = 1<<1, /* abort and disable edma */
+ EdmaAbort = 1<<1, /* abort and disable edma */
Atareset = 1<<2, /* reset sata transport, link, physical layers */
EdmaFreeze = 1<<4, /* do not process new requests from queue */
@@ -184,8 +187,8 @@
CSPDgen2 = 2<<4, /* <= gen2 */
CIPMmask = 0xf<<8,
CIPMany = 0<<8, /* no interface power management state restrictions */
- CIPMpartial = 1<<8, /* no transition to PARTIAL */
- CIPMslumber = 1<<9, /* no transition to SLUMBER */
+ CIPMnopartial = 1<<8, /* no transition to PARTIAL */
+ CIPMnoslumber = 1<<9, /* no transition to SLUMBER */
CSPMmask = 0xf<<12,
CSPMnone = 0<<12, /* no different state for select power management */
CSPMpartial = 1<<12, /* to PARTIAL */
@@ -232,7 +235,7 @@
v = hr->intrmain;
diprint("intr %#lux, main %#lux\n", hr->intr, v);
if(v & Sata1err) {
- diprint("intre %#lux\n", sr->intre);
+ diprint("intre %#lux\n", sr->edma.intre);
diprint("m 1err\n");
}
if(v & Sata1done) {
@@ -241,17 +244,17 @@
if(v & Sata1dmadone) {
diprint("m 1dmadone\n");
}
- hr->intr = 0; // clear
- sr->intre = 0; // clear
-
- if(sr->ncqdone)
- iprint("ncqdone %#lux\n", sr->ncqdone);
- diprint("ncqdone %#lux\n", sr->ncqdone);
- diprint("reqin %#lux reqout %#lux respin %#lux respout %#lux\n",
sr->reqin, sr->reqout, sr->respin, sr->respout);
+ hr->intr = 0;
+ sr->edma.intre = 0;
+
+ if(sr->edma.ncqdone)
+ iprint("ncqdone %#lux\n", sr->edma.ncqdone);
+ diprint("ncqdone %#lux\n", sr->edma.ncqdone);
+ diprint("reqin %#lux reqout %#lux respin %#lux respout %#lux\n",
sr->edma.reqin, sr->edma.reqout, sr->edma.respin, sr->edma.respout);
dcinv(resps, 32*sizeof resps[0]);
- in = (sr->respin & MASK(8))/sizeof (Resp);
- out = (sr->respout & MASK(8))/sizeof (Resp);
+ in = (sr->edma.respin & MASK(8))/sizeof (Resp);
+ out = (sr->edma.respout & MASK(8))/sizeof (Resp);
for(;;) {
if(in == out)
break;
@@ -265,13 +268,7 @@
/* xxx check for error */
wakeup(&reqsr[out]);
out = (out+1)%32;
- sr->respout = (ulong)&resps[out];
- }
-
- /* xxx testing */
- if(count++ >= 100) {
- intrdisable(Irqlo, IRQ0sata, sataintr, nil, "sata1");
- diprint("no more intr for now\n");
+ sr->edma.respout = (ulong)&resps[out];
}
intrclear(Irqlo, IRQ0sata);
@@ -318,16 +315,10 @@
/* xxx sleep until edma is disabled or edma is idle (edma status, bit 7
(EDMAIdle). then disable edma. */
- hr->intrmainmask &= ~(Sata1err|Sata1done|Sata1dmadone);
-
- /* xxx should do this once? or not at all? */
- sr->ifccfg |= Ignorebsy;
- sr->fiscfg = 0;
- sr->fisintr = ~0;
- sr->fisintrmask = 0;
-
- //print("pio, status %#lux\n", a->status);
- //a->ctl = 1<<1;
+ /* xxx don't blindly reset registers later */
+ hr->intrmainena &= ~(Sata1err|Sata1done|Sata1dmadone);
+
+ diprint("pio, status %#lux\n", a->status);
a->feat = feat;
a->sectors = sectors;
a->lbalow = (lba>>0) & 0xff;
@@ -337,13 +328,13 @@
a->cmd = cmd;
delay(100);
v = a->status;
-if(0) {
- print("result, status %#lux\n", v);
- if(v & Aerr) print(" err\n");
- if(v & Adrq) print(" drq\n");
- if(v & Adf) print(" df\n");
- if(v & Adrdy) print(" drdy\n");
- if(v & Absy) print(" bsy\n");
+if(satadebug) {
+ diprint("result, status %#lux\n", v);
+ if(v & Aerr) diprint(" err\n");
+ if(v & Adrq) diprint(" drq\n");
+ if(v & Adf) diprint(" df\n");
+ if(v & Adrdy) diprint(" drdy\n");
+ if(v & Absy) diprint(" bsy\n");
}
/* xxx check for & propagate errors */
@@ -358,7 +349,7 @@
break;
}
- hr->intrmainmask |= Sata1err|Sata1done|Sata1dmadone;
+ hr->intrmainena |= Sata1err|Sata1done|Sata1dmadone;
hr->intr = 0;
return v;
}
@@ -392,7 +383,7 @@
for(i = 0; i < 512; i++)
c += buf[i];
if(c != 0) {
- print("check byte for 'identify device' response invalid\n");
+ dprint("check byte for 'identify device' response invalid\n");
return -1;
}
@@ -409,7 +400,7 @@
v = g16(buf+83*2);
if((v & (1<<10)) == 0) {
- print("lba48 not supported (word 83 %#lux)\n", v);
+ dprint("lba48 not supported (word 83 %#lux)\n", v);
return -1;
}
@@ -419,13 +410,13 @@
/* xxx check ncq support, how? */
-if(0) {
- print("model %q\n", disk.model);
- print("serial %q\n", disk.serial);
- print("firmware %q\n", disk.firmware);
- print("sectors %llud\n", disk.sectors);
- print("size %llud bytes\n", disk.sectors*512);
- print("size %llud gb\n", disk.sectors*512/(1024*1024*1024));
+if(satadebug) {
+ dprint("model %q\n", disk.model);
+ dprint("serial %q\n", disk.serial);
+ dprint("firmware %q\n", disk.firmware);
+ dprint("sectors %llud\n", disk.sectors);
+ dprint("size %llud bytes\n", disk.sectors*512);
+ dprint("size %llud gb\n", disk.sectors*512/(1024*1024*1024));
}
satadir[Qdata].length = disk.sectors*512;
disk.valid = 1;
@@ -440,64 +431,186 @@
}
static void
-satareset(void)
-{
- /* power up sata1 port */
- CPUCSREG->mempm &= ~Sata1mem;
- CPUCSREG->clockgate |= Sata1clock;
- regreadl(&CPUCSREG->clockgate);
-
- SATA1REG->ifccfg &= ~(1<<9);
-}
+atadump(void)
+{
+ ulong n;
+ char *buf, *p, *e;
+ AtaReg *a = ATA1REG;
+
+ n = 2048;
+ p = buf = smalloc(n);
+ e = p+n;
+
+ p = seprint(p, e, "ata:\n");
+ p = seprint(p, e, " data %04lux\n", a->data);
+ p = seprint(p, e, " feat/error %02lux\n", a->feat);
+ p = seprint(p, e, " sectors %02lux\n", a->sectors);
+ p = seprint(p, e, " lbalow %02lux\n", a->lbalow);
+ p = seprint(p, e, " lbamid %02lux\n", a->lbamid);
+ p = seprint(p, e, " lbahigh %02lux\n", a->lbahigh);
+ p = seprint(p, e, " dev %02lux\n", a->dev);
+ p = seprint(p, e, " cmd/status %02lux\n", a->cmd);
+ p = seprint(p, e, " ctl %02lux\n", a->ctl);
+ USED(p);
+
+ dprint("%s", buf);
+
+ free(buf);
+}
+
static void
-satainit(void)
+satareset(void)
{
SatahcReg *hr = SATAHCREG;
SataReg *sr = SATA1REG;
- /* xxx should enable phy too, perhaps reset, and do the phy errata dance
*/
-
- if((sr->sstatus & SDETmask) != SDETdevphy) {
- print("no sata disk attached, skipping satainit\n");
- return;
- }
-
- SATAHCREG->intrmainmask &= ~(1<<8); // no interrupt coalescing for now
+ /* power up sata1 port */
+ CPUCSREG->mempm &= ~Sata1mem;
+ CPUCSREG->clockgate |= Sata1clock;
+ regreadl(&CPUCSREG->clockgate);
+
+ /* disable interrupts */
+ hr->intrmainena = 0;
+ sr->edma.intreena = 0;
+ sr->ifc.serrintrena = 0;
+ sr->ifc.fisintrena = 0;
+
+ /* clear interrupts */
+ sr->edma.intre = 0;
+ /* xxx more */
+
+ /* disable & abort edma, bdma */
+ sr->edma.cmd = (sr->edma.cmd & ~EdmaEnable) | EdmaAbort;
+
+ /* xxx should set full register? */
+ sr->ifc.ifccfg &= ~Physhutdown;
+
+ /* xxx reset more registers */
+ hr->cfg = (0xff<<0) /* default mbus arbiter timeout value */
+ | (1<<8) /* no dma byte swap */
+ | (1<<9) /* no edma byte swap */
+ | (1<<10) /* no prdp byte swap */
+ | (1<<16); /* mbus arbiter timer disabled */
+ hr->intrcoalesc = 0; /* raise interrupt after 0 completions (disable
coalescing) */
+ hr->intrtime = 0; /* number of clocks before asserting interrupt (disable
coalescing) */
+ hr->intr = 0; /* clear */
+
+/* xxx should set windows correct too */
+if(0) {
+ hr->win[0].ctl = (1<<0) /* enable window */
+ | (0<<1) /* mbus write burst limit. 0: no limit (max 128 bytes), 1: do
not cross 32 byte boundary */
+ | ((0 & 0x0f)<<4) /* target */
+ | ((0xe & 0xff)<<8) /* target attributes */
+ | ((0xfff & 0xffff)<<16); /* size of window, number+1 64kb units */
+ hr->win[0].base = 0x0 & 0xffff;
+}
reqs = xspanalloc(32*sizeof reqs[0], 32*sizeof reqs[0], 0);
resps = xspanalloc(32*sizeof resps[0], 32*sizeof resps[0], 0);
prds = xspanalloc(32*8*sizeof prds[0], 16, 0);
if(reqs == nil || resps == nil || prds == nil)
- panic("satainit");
+ panic("satareset");
memset(reqs, 0, 32*sizeof reqs[0]);
memset(resps, 0, 32*sizeof resps[0]);
memset(prds, 0, 32*8*sizeof prds[0]);
reqnext = respnext = 0;
- sr->reqbasehi = sr->respbasehi = 0;
- sr->reqin = 0;
- sr->reqout = 0;
- sr->respin = 0;
- sr->respout = (ulong)&resps[0];
-
- diprint("satainit, reqin %#lux, reqout %#lux\n", sr->reqin, sr->reqout);
-
- if(identify() < 0) {
- print("no disk\n");
- return;
- }
- print("#S/sd01: %q, %lludGB (%,llud bytes), sata-i%s\n", disk.model,
disk.sectors*512/(1024*1024*1024), disk.sectors*512, (SATA1REG->sstatus &
SSPDgen2) ? "i" : "");
-
- hr->intrmainmask = Sata1err|Sata1done|Sata1dmadone;
- hr->intr = 0; // clear
- sr->intre = 0; // clear
-
- diprint("satainit, before edma, hr->intr %#lux, hr->intrmain %#lux,
sr->intre %#lux\n", hr->intr, hr->intrmain, sr->intre);
-
- /* set interrupts */
- intrenable(Irqlo, IRQ0sata, sataintr, nil, "sata1");
-
+ intrenable(Irqlo, IRQ0sata, sataintr, nil, "sata");
+}
+
+static void
+satainit(void)
+{
+ SatahcReg *hr = SATAHCREG;
+ SataReg *sr = SATA1REG;
+ int n;
+
+ diprint("satainit...\n");
+
+ /* disable interrupts */
+ hr->intrmainena = 0;
+ sr->edma.intreena = 0;
+ sr->ifc.serrintrena = 0;
+ sr->ifc.fisintrena = 0;
+
+ /* disable & abort edma */
+ sr->edma.cmd = (sr->edma.cmd & ~EdmaEnable) | EdmaAbort;
+
+ /* clear edma */
+ sr->edma.reqbasehi = sr->edma.respbasehi = 0;
+ sr->edma.reqin = 0;
+ sr->edma.reqout = 0;
+ sr->edma.respin = 0;
+ sr->edma.respout = (ulong)&resps[0];
+
+ diprint("satainit, reqin %#lux, reqout %#lux\n", sr->edma.reqin,
sr->edma.reqout);
+
+if(0) {
+ dprint("ata before reset\n");
+ atadump();
+}
+
+ dprint("sr->ifc.sstatus before edma reset %#lux\n", sr->ifc.sstatus);
+
+ sr->edma.cmd |= Atareset;
+ delay(1);
+ sr->edma.cmd &= ~Atareset;
+ delay(200);
+
+ /* errata magic, to fix the phy. see uboot code (no docs available). */
+ sr->ifc.phym3 = (sr->ifc.phym3 & ~0x78100000) | 0x28000000;
+ sr->ifc.phym4 = (sr->ifc.phym4 & ~1) | (1<<16);
+ sr->ifc.phym9g2 = (sr->ifc.phym9g2 & ~0x400f) | 0x00008; /* tx driver
amplitude */
+ sr->ifc.phym9g1 = (sr->ifc.phym9g1 & ~0x400f) | 0x00008; /* tx driver
amplitude */
+ delay(100); /* needed? */
+
+ diprint("before phy init, sstatus %#lux, serror %#lux\n",
sr->ifc.sstatus, sr->ifc.serror);
+
+ sr->ifc.scontrol = CDETcomm|CSPDany|CIPMnopartial|CIPMnoslumber;
+ regreadl(&sr->ifc.scontrol);
+ delay(1);
+ dprint("sr->ifc.sstatus after phy reset %#lux\n", sr->ifc.sstatus);
+
+ sr->ifc.scontrol &= ~CDETcomm;
+ regreadl(&sr->ifc.scontrol);
+ microdelay(20*1000);
+
+ /* check phy status */
+ n = 0;
+ while((sr->ifc.sstatus & SDETmask) != SDETdevphy) {
+ if(n++ > 200) {
+ dprint("no sata disk attached (sstatus %#lux; serror %#lux), aborting
sata init\n", sr->ifc.sstatus, sr->ifc.serror);
+ return;
+ }
+ delay(1);
+ }
+
+ diprint("after phy init, have connection, sstatus %#lux, serror %#lux\n",
sr->ifc.sstatus, sr->ifc.serror);
+
+ sr->ifc.ifccfg &= ~Ignorebsy;
+
+if(0) {
+ tsleep(&up->sleep, return0, nil, 500);
+ dprint("ata after real reset\n");
+ atadump();
+}
+
+ dprint("sr->ifc.sstatus before ata identify %#lux\n", sr->ifc.sstatus);
+
+ /* xxx horrible, should properly wait during command execution, until
device no longer busy */
+ tsleep(&up->sleep, return0, nil, 1000);
+ if(identify() < 0) {
+ dprint("no disk\n");
+ return;
+ }
+ dprint("#S/sd01: %q, %lludGB (%,llud bytes), sata-i%s\n", disk.model,
disk.sectors*512/(1024*1024*1024), disk.sectors*512, (SATA1REG->ifc.sstatus
& SSPDgen2) ? "i" : "");
+
+ hr->intrmainena = Sata1err|Sata1done|Sata1dmadone;
+ hr->intr = 0;
+ sr->edma.intre = 0;
+
+ diprint("satainit, before edma, hr->intr %#lux, hr->intrmain %#lux,
sr->edma.intre %#lux\n", hr->intr, hr->intrmain, sr->edma.intre);
}
static char *dets[] = {"none", "dev", nil, "devphy", "nophy"};
@@ -533,6 +646,7 @@
AtaReg *a = ATA1REG;
ulong v;
int i;
+ ulong *w;
USED(a);
@@ -551,7 +665,7 @@
p = seprint(p, e, "\n");
v = hr->intrmain;
- p = seprint(p, e, "hc intrmain %#lux, mask %#lux\n", v, hr->intrmainmask);
+ p = seprint(p, e, "hc intrmain %#lux, ena %#lux\n", v, hr->intrmainena);
if(v & Sata1err) p = seprint(p, e, " sata1err");
if(v & Sata1done) p = seprint(p, e, " sata1done");
if(v & Sata1dmadone) p = seprint(p, e, " sata1dmadone");
@@ -560,9 +674,9 @@
if(v) p = seprint(p, e, " other: %#lux", v);
p = seprint(p, e, "\n");
- p = seprint(p, e, "ncqdone %#lux\n", sr->ncqdone);
-
- v = sr->ifccfg;
+ p = seprint(p, e, "ncqdone %#lux\n", sr->edma.ncqdone);
+
+ v = sr->ifc.ifccfg;
p = seprint(p, e, "ifccfg %#lux\n", v);
if(v & SSC) p = seprint(p, e, " ssc");
if(v & Gen2) p = seprint(p, e, " gen2en");
@@ -573,14 +687,14 @@
if(v & Emphpre) p = seprint(p, e, " emphpre");
p = seprint(p, e, "\n");
- v = sr->cfg;
+ v = sr->edma.cfg;
p = seprint(p, e, "cfg %#lux", v);
if(v & ECFGncq) p = seprint(p, e, " (ncq)");
if(v & ECFGqueue) p = seprint(p, e, " (queued)");
p = seprint(p, e, "\n");
- v = sr->intre;
- p = seprint(p, e, "intre %#lux, mask %#lux\n", v, sr->intremask);
+ v = sr->edma.intre;
+ p = seprint(p, e, "intre %#lux, enabled %#lux\n", v,
sr->edma.intreena);
if(v) {
if(v & Edeverr) p = seprint(p, e, " deverr");
if(v & Edevdis) p = seprint(p, e, " devdis");
@@ -588,23 +702,23 @@
if(v & Eserror) p = seprint(p, e, " serror");
if(v & Eselfdis) p = seprint(p, e, " selfdis");
if(v & Etransint) p = seprint(p, e, " transint");
- if(v & Eiordy) p = seprint(p, e, " iodry");
+ if(v & Eiordy) p = seprint(p, e, " iordy");
if(v & (1<<31)) p = seprint(p, e, " transerr");
p = seprint(p, e, " rx %#lux %#lux, tx %#lux %#lux", (v>>13)&0xf,
(v>>17)&0xf, (v>>21)&0xf, (v>>26)&0xf);
p = seprint(p, e, "\n");
}
- v = sr->cmd;
+ v = sr->edma.cmd;
p = seprint(p, e, "cmd %#lux\n", v);
if(v & EdmaEnable) p = seprint(p, e, " edma enable\n");
- v = sr->status;
+ v = sr->edma.status;
p = seprint(p, e, "status %#lux\n", v);
- p = seprint(p, e, "req %#lux %#lux\n", sr->reqin, sr->reqout);
- p = seprint(p, e, "resp %#lux %#lux\n", sr->respin, sr->respout);
-
- v = sr->sstatus;
+ p = seprint(p, e, "req %#lux %#lux\n", sr->edma.reqin,
sr->edma.reqout);
+ p = seprint(p, e, "resp %#lux %#lux\n", sr->edma.respin,
sr->edma.respout);
+
+ v = sr->ifc.sstatus;
p = seprint(p, e, "sstatus %#lux\n", v);
s = "unknown";
switch(v&0xf) {
@@ -622,18 +736,18 @@
if(v & SSPDgen2) p = seprint(p, e, " gen2");
p = seprint(p, e, " ipm: %#lux\n", (v>>8)&0xf);
- v = sr->serror;
+ v = sr->ifc.serror;
p = seprint(p, e, "serror %#lux ", v);
for(i = 0; i < nelem(serrors); i++)
if(v & serrors[i].v)
p = seprint(p, e, "%s", serrors[i].s);
p = seprint(p, e, "\n");
- p = seprint(p, e, "scontrol %#lux\n", sr->scontrol);
-
- p = seprint(p, e, "ifcctl %#lux\n", sr->ifcctl);
- p = seprint(p, e, "ifctestctl %#lux\n", sr->ifctestctl);
- v = sr->ifcstatus;
+ p = seprint(p, e, "scontrol %#lux\n", sr->ifc.scontrol);
+
+ p = seprint(p, e, "ifcctl %#lux\n", sr->ifc.ifcctl);
+ p = seprint(p, e, "ifctestctl %#lux\n", sr->ifc.ifctestctl);
+ v = sr->ifc.ifcstatus;
p = seprint(p, e, "ifcstatus %#lux\n", v);
p = seprint(p, e, " fistype %#lux, pmrx %#lux, transfsm %#lux\n",
v&0xff, (v>>8)&0xf, (v>>24)&0xf);
if(v & (1<<12)) p = seprint(p, e, " vendoruqdn");
@@ -652,31 +766,32 @@
if(v & (1<<31)) p = seprint(p, e, " N");
p = seprint(p, e, "\n");
- p = seprint(p, e, "fiscfg %#lux\n", sr->fiscfg);
- p = seprint(p, e, "fisintr %#lux, mask %#lux\n", sr->fisintr,
sr->fisintrmask);
- p = seprint(p, e, "fis[7] %#lux %#lux %#lux %#lux %#lux %#lux %#lux\n",
sr->fis[0], sr->fis[1], sr->fis[2], sr->fis[3], sr->fis[4], sr->fis[5],
sr->fis[6]);
+ p = seprint(p, e, "fiscfg %#lux\n", sr->ifc.fiscfg);
+ p = seprint(p, e, "fisintr %#lux, ena %#lux\n", sr->ifc.fisintr,
sr->ifc.fisintrena);
+ w = sr->ifc.fis;
+ p = seprint(p, e, "fis[7] %#lux %#lux %#lux %#lux %#lux %#lux %#lux\n",
+ w[0], w[1], w[2], w[3], w[4], w[5], w[6]);
if(0) {
- p = seprint(p, e, "pll 0x%08lux\n", sr->pllcfg);
- p = seprint(p, e, "ltmode 0x%08lux\n", sr->ltmode);
- p = seprint(p, e, "phym3 0x%08lux\n", sr->phym3);
- p = seprint(p, e, "phym4 0x%08lux\n", sr->phym4);
- p = seprint(p, e, "phym1 0x%08lux\n", sr->phym1);
- p = seprint(p, e, "phym2 0x%08lux\n", sr->phym2);
- p = seprint(p, e, "bistctl 0x%08lux\n", sr->bistctl);
- p = seprint(p, e, "bist1 0x%08lux\n", sr->bist1);
- p = seprint(p, e, "bist2 0x%08lux\n", sr->bist2);
- p = seprint(p, e, "vendor 0x%08lux\n", sr->vendor);
- p = seprint(p, e, "phym9g2 0x%08lux\n", sr->phym9g2);
- p = seprint(p, e, "phym9g1 0x%08lux\n", sr->phym9g1);
- p = seprint(p, e, "phycfg 0x%08lux\n", sr->phycfg);
- p = seprint(p, e, "phytctl 0x%08lux\n", sr->phytctl);
- p = seprint(p, e, "phym10 0x%08lux\n", sr->phym10);
- p = seprint(p, e, "phym12 0x%08lux\n", sr->phym12);
+ p = seprint(p, e, "pll 0x%08lux\n", sr->ifc.pllcfg);
+ p = seprint(p, e, "ltmode 0x%08lux\n", sr->ifc.ltmode);
+ p = seprint(p, e, "phym3 0x%08lux\n", sr->ifc.phym3);
+ p = seprint(p, e, "phym4 0x%08lux\n", sr->ifc.phym4);
+ p = seprint(p, e, "phym1 0x%08lux\n", sr->ifc.phym1);
+ p = seprint(p, e, "phym2 0x%08lux\n", sr->ifc.phym2);
+ p = seprint(p, e, "bistctl 0x%08lux\n", sr->ifc.bistctl);
+ p = seprint(p, e, "bist1 0x%08lux\n", sr->ifc.bist1);
+ p = seprint(p, e, "bist2 0x%08lux\n", sr->ifc.bist2);
+ p = seprint(p, e, "vendor 0x%08lux\n", sr->ifc.vendor);
+ p = seprint(p, e, "phym9g2 0x%08lux\n", sr->ifc.phym9g2);
+ p = seprint(p, e, "phym9g1 0x%08lux\n", sr->ifc.phym9g1);
+ p = seprint(p, e, "phycfg 0x%08lux\n", sr->ifc.phycfg);
+ p = seprint(p, e, "phytctl 0x%08lux\n", sr->ifc.phytctl);
+ p = seprint(p, e, "phym10 0x%08lux\n", sr->ifc.phym10);
+ p = seprint(p, e, "phym12 0x%08lux\n", sr->ifc.phym12);
}
-
-if(0) {
+if(1) {
p = seprint(p, e, "ata:\n");
p = seprint(p, e, " data %04lux\n", a->data);
p = seprint(p, e, " feat/error %02lux\n", a->feat);
@@ -758,7 +873,7 @@
if(nb % 512 != 0)
error(Ebadarg);
if((ulong)buf & 1)
- error(Ebadarg); // fix, should alloc buffer and copy it afterwards?
+ error(Ebadarg); /* fix, should alloc buffer and copy it afterwards? */
if(lba == disk.sectors)
return 0;
@@ -797,22 +912,22 @@
nslo = ns&0xff;
nshi = (ns>>8)&0xff;
dev = 1<<6;
- rq->ata[0] = (cmds[t]<<16)|(nslo<<24); // cmd, feat current
- rq->ata[1] = (lbalo<<0)|(dev<<24); // 24 bit lba current, dev
- rq->ata[2] = (lbahi<<0)|(nshi<<24); // 24 bit lba previous, feat
ext/previous
- rq->ata[3] = ((i<<3)<<0)|(0<<8); // sectors current (tag), previous
+ rq->ata[0] = (cmds[t]<<16)|(nslo<<24); /* cmd, feat current */
+ rq->ata[1] = (lbalo<<0)|(dev<<24); /* 24 bit lba current, dev */
+ rq->ata[2] = (lbahi<<0)|(nshi<<24); /* 24 bit lba previous, feat
ext/previous */
+ rq->ata[3] = ((i<<3)<<0)|(0<<8); /* sectors current (tag), previous */
dcwbinv(rq, sizeof rq[0]);
- sr->fiscfg = (1<<6)-1;
- sr->fisintr = ~0;
- sr->fisintrmask = 0;
+ sr->ifc.fiscfg = (1<<6)-1;
+ sr->ifc.fisintr = ~0;
+ sr->ifc.fisintrena = 0;
diprint("io, using slot %d, off %llud\n", i, off);
v = 1<<i;
satadone &= ~v;
- sr->reqin = (ulong)&reqs[reqnext];
- if((sr->cmd & EdmaEnable) == 0) {
- sr->cfg |= ECFGncq|0x1f; // 0x1f for queue depth?
- sr->cmd = EdmaEnable;
+ sr->edma.reqin = (ulong)&reqs[reqnext];
+ if((sr->edma.cmd & EdmaEnable) == 0) {
+ sr->edma.cfg |= ECFGncq|0x1f; /* 0x1f for queue depth? */
+ sr->edma.cmd = EdmaEnable;
}
qunlock(&reqsl);
@@ -826,15 +941,27 @@
ctl(char *buf, long n)
{
Cmdbuf *cb;
- SataReg *sr = SATA1REG;
cb = parsecmd(buf, n);
+ if(strcmp(cb->f[0], "debug") == 0) {
+ if(cb->nf != 2)
+ error(Ebadarg);
+ satadebug = atoi(cb->f[1]);
+ return n;
+ }
if(strcmp(cb->f[0], "reset") == 0) {
- sr->cmd = Atareset;
- sr->cmd &= ~Atareset;
- /* xxx much more */
+ if(cb->nf != 1)
+ error(Ebadarg);
+ satainit();
return n;
}
+ if(strcmp(cb->f[0], "identify") == 0) {
+ if(identify() < 0) {
+ error("no disk");
+ }
+ dprint("#S/sd01: %q, %lludGB (%,llud bytes), sata-i%s\n", disk.model,
disk.sectors*512/(1024*1024*1024), disk.sectors*512, (SATA1REG->ifc.sstatus
& SSPDgen2) ? "i" : "");
+ return n;
+ }
error("bad ctl");
return -1;
}
@@ -913,9 +1040,9 @@
free(s);
return n;
case Qdata:
-print("dcwbinv0 %ld\n", n);
+diprint("dcwbinv0 %ld\n", n);
dcwbinv(buf, n);
-print("dcwbinv1 %ld\n", n);
+diprint("dcwbinv1 %ld\n", n);
r = 0;
while(r < n) {
nn = io(Read, (uchar*)buf+r, n-r, off+r);
@@ -938,7 +1065,7 @@
switch((ulong)c->qid.path){
case Qctl:
- error(Ebadarg);
+ return ctl(buf, n);
case Qdata:
dcwbinv(buf, n);
r = 0;
@@ -950,7 +1077,7 @@
}
return r;
case Qtest:
- return ctl(buf, n);
+ break;
}
error(Egreg);
return 0; /* not reached */
=======================================
--- /io.h Thu Mar 18 06:11:29 2010
+++ /io.h Wed Aug 25 14:36:10 2010
@@ -845,7 +845,7 @@
ulong intr;
ulong _pad0[2];
ulong intrmain;
- ulong intrmainmask;
+ ulong intrmainena;
ulong _pad1;
ulong ledcfg;
struct {
@@ -861,78 +861,76 @@
struct SataReg
{
/* edma */
- ulong cfg;
- ulong _pad0;
- ulong intre;
- ulong intremask;
- ulong reqbasehi;
- ulong reqin;
- ulong reqout;
- ulong respbasehi;
- ulong respin;
- ulong respout;
- ulong cmd;
- ulong _pad1;
- ulong status;
- ulong iordytimeout;
- ulong _pad2[2];
- ulong cmddelaythr;
- uchar _pad3[0x50-0x44];
-
- /* sata interface */
- ulong ifccfg;
- ulong pllcfg;
- uchar _pad4[0x60-0x58];
-
- /* edma */
- ulong haltcond;
- uchar _pad5[0x94-0x64];
- ulong ncqdone;
- uchar _pad6[0x224-0x98];
-
- /* basic dma */
- struct {
- ulong cmd;
- ulong status;
- ulong dtlo;
- ulong dthi;
- ulong drlo;
- ulong drhi;
- } bdma;
- uchar _pad7[0x300-0x23c];
-
- /* sata interface */
- ulong sstatus;
- ulong serror;
- ulong scontrol;
- ulong ltmode;
- ulong phym3;
- ulong phym4;
- ulong _pad8[5];
- ulong phym1;
- ulong phym2;
- ulong bistctl;
- ulong bist1;
- ulong bist2;
- ulong serrintrmask;
- ulong ifcctl;
- ulong ifctestctl;
- ulong ifcstatus;
- ulong _pad9[3];
- ulong vendor;
- ulong fiscfg;
- ulong fisintr;
- ulong fisintrmask;
- ulong _pad10;
- ulong fis[7];
- ulong _pad11[3];
- ulong phym9g2;
- ulong phym9g1;
- ulong phycfg;
- ulong phytctl;
- ulong phym10;
- ulong _pad12;
- ulong phym12;
+ union {
+ struct {
+ uchar _pad0[0x224];
+ ulong cmd;
+ ulong status;
+ ulong dtlo;
+ ulong dthi;
+ ulong drlo;
+ ulong drhi;
+ } bdma;
+ struct {
+ ulong cfg;
+ ulong _pad0;
+ ulong intre;
+ ulong intreena;
+ ulong reqbasehi;
+ ulong reqin;
+ ulong reqout;
+ ulong respbasehi;
+ ulong respin;
+ ulong respout;
+ ulong cmd;
+ ulong _pad1;
+ ulong status;
+ ulong iordytimeout;
+ ulong _pad2[2];
+ ulong cmddelaythr;
+ uchar _pad3[0x60-0x44];
+ ulong haltcond;
+ uchar _pad5[0x94-0x64];
+ ulong ncqdone;
+ } edma;
+ struct {
+ uchar _pad0[0x50-0x0];
+ ulong ifccfg;
+ ulong pllcfg;
+ uchar _pad4[0x300-0x58];
+ ulong sstatus;
+ ulong serror;
+ ulong scontrol;
+ ulong ltmode;
+ ulong phym3;
+ ulong phym4;
+ ulong _pad8[5];
+ ulong phym1;
+ ulong phym2;
+ ulong bistctl;
+ ulong bist1;
+ ulong bist2;
+ ulong serrintrena;
+ ulong ifcctl;
+ ulong ifctestctl;
+ ulong ifcstatus;
+ ulong _pad9[3];
+ ulong vendor;
+ ulong fiscfg;
+ ulong fisintr;
+ ulong fisintrena;
+ ulong _pad10;
+ ulong fis[7];
+ ulong _pad11[3];
+ ulong phym9g2;
+ ulong phym9g1;
+ ulong phycfg;
+ ulong phytctl;
+ ulong phym10;
+ ulong _pad12;
+ ulong phym12;
+ } ifc;
+ };
};
#define ATA0REG ((AtaReg*)AddrAta0)