M pc/devi82365.c => pc/devi82365.c +56 -31
@@ 41,6 41,9 @@ enum
Rwe= 0x6, /* address window enable */
Fmem16= (1<<5), /* use A23-A12 to decode address */
Rio= 0x7, /* I/O control */
+ Fwidth16= (1<<0), /* 16 bit data width */
+ Fiocs16= (1<<1), /* IOCS16 determines data width */
+ Ftiming= (1<<3), /* timing register to use */
Riobtm0lo= 0x8, /* I/O address 0 start low byte */
Riobtm0hi= 0x9, /* I/O address 0 start high byte */
Riotop0lo= 0xa, /* I/O address 0 stop low byte */
@@ 126,6 129,7 @@ struct Conftab
int index;
ushort irqs; /* legal irqs */
ushort port; /* port address */
+ uchar irqtype;
uchar nioregs; /* number of io registers */
uchar bit16; /* true for 16 bit access */
uchar vpp1;
@@ 239,11 243,17 @@ slotena(Slot *pp)
if(pp->enabled)
return;
- /* power up and reset, wait's are empirical (???) */
+ /* power up and unreset, wait's are empirical (???) */
+ wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
+ delay(300);
+ wrreg(pp, Rigc, Fnotreset);
+ delay(500);
+
+ wrreg(pp, Rpc, 0);
+ delay(500);
+
wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
delay(300);
- wrreg(pp, Rigc, 0);
- delay(100);
wrreg(pp, Rigc, Fnotreset);
delay(500);
@@ 253,7 263,7 @@ slotena(Slot *pp)
cisread(pp);
pp->enabled = 1;
} else
- wrreg(pp, Rpc, Fautopower);
+ wrreg(pp, Rpc, 0);
}
/*
@@ 262,8 272,8 @@ slotena(Slot *pp)
static void
slotdis(Slot *pp)
{
- wrreg(pp, Rpc, Fautopower); /* turn off card */
- wrreg(pp, Rwe, 0); /* no windows */
+ wrreg(pp, Rwe, 0); /* no windows */
+ wrreg(pp, Rpc, 0); /* turn off card power */
pp->enabled = 0;
}
@@ 606,10 616,7 @@ i82365reset(void)
pp->memlen = 64*MB;
pp->base = (cp->dev<<7) | (j<<6);
pp->cp = cp;
-if(pp == slot)i82365dump(pp);
-/*
slotdis(pp);
-*/
/* interrupt on status change */
wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena);
@@ 796,6 803,16 @@ i82365read(Chan *c, void *a, long n, ulong offset)
if(pp->busy)
cp += sprint(cp, "busy\n");
cp += sprint(cp, "battery lvl %d\n", pp->battery);
+{
+ int i;
+
+ for(i = 0; i < 0x40; i++){
+ if((i&0x7) == 0)
+ cp += sprint(cp, "\n%ux: ", i);
+ cp += sprint(cp, "%ux ", rdreg(pp, i));
+ }
+ cp += sprint(cp, "\n");
+}
*cp = 0;
return readstr(offset, a, n, buf);
default:
@@ 915,13 932,16 @@ pcmio(int slotno, ISAConf *isa)
isa->irq = 9;
wrreg(pp, Rigc, isa->irq | Fnotreset | Fiocard);
- /* set power and enable slotnoice */
+ /* set power and enable device */
x = vcode(ct->vpp1);
wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
/* 16-bit data path */
if(ct->bit16)
- wrreg(pp, Rio, (1<<0)|(1<<1));
+ x = Fiocs16|Fwidth16;
+ else
+ x = 0;
+ wrreg(pp, Rio, Ftiming|x);
/* enable io port map 0 */
if(isa->port == 0)
@@ 929,8 949,8 @@ pcmio(int slotno, ISAConf *isa)
we = rdreg(pp, Rwe);
wrreg(pp, Riobtm0lo, isa->port);
wrreg(pp, Riobtm0hi, isa->port>>8);
- wrreg(pp, Riotop0lo, (isa->port+ct->nioregs));
- wrreg(pp, Riotop0hi, (isa->port+ct->nioregs)>>8);
+ wrreg(pp, Riotop0lo, (isa->port+ct->nioregs-1));
+ wrreg(pp, Riotop0hi, (isa->port+ct->nioregs-1)>>8);
wrreg(pp, Rwe, we | (1<<6));
/* only touch Rconfig if it is present */
@@ 938,21 958,14 @@ pcmio(int slotno, ISAConf *isa)
/* Reset adapter */
m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1);
p = (uchar*)(KZERO|(m->isa + pp->caddr + Rconfig - m->ca));
-if(strstr(pp->verstr, "KeepInTouch") == 0){
- *p = Creset;
- delay(5);
- *p = 0;
- delay(5);
-}
- /* set configuration */
-if(strstr(pp->verstr, "KeepInTouch") == 0){
- if(isa->irq > 7)
- *p = Clevel | ct->index;
- else
- *p = ct->index;
+ /* set configuration and interrupt type */
+ x = ct->index;
+ if((ct->irqtype & 0x20) && ((ct->irqtype & 0x40)==0 || isa->irq>7))
+ x |= Clevel;
+ *p = x|ct->index;
delay(5);
-} else i82365dump(pp);
+
pcmunmap(slotno, m);
}
return 0;
@@ 1066,15 1079,26 @@ microvolt(Slot *pp)
{
uchar c;
ulong microvolts;
+ ulong exp;
if(readc(pp, &c) != 1)
return 0;
- microvolts = vexp[c&0x7]*vmant[(c>>3)&0xf];
+ exp = vexp[c&0x7];
+ microvolts = vmant[(c>>3)&0xf]*exp;
while(c & 0x80){
if(readc(pp, &c) != 1)
return 0;
- if(c == 0x7d || c == 0x7e || c == 0x7f)
- microvolts = 0;
+ switch(c){
+ case 0x7d:
+ break; /* high impedence when sleeping */
+ case 0x7e:
+ case 0x7f:
+ microvolts = 0; /* no connection */
+ break;
+ default:
+ exp /= 10;
+ microvolts += exp*(c&0x7f);
+ }
}
return microvolts;
}
@@ 1121,7 1145,7 @@ power(Slot *pp)
nanoamps(pp);
if(feature & 0x20)
nanoamps(pp);
- if(feature & 0x20)
+ if(feature & 0x40)
nanoamps(pp);
return mv/1000000;
}
@@ 1195,6 1219,7 @@ irq(Slot *pp, Conftab *ct)
if(readc(pp, &c) != 1)
return;
+ ct->irqtype = c & 0xe0;
if(c & 0x10)
ct->irqs = getlong(pp, 2);
else
@@ 1271,7 1296,7 @@ tentry(Slot *pp, int ttype)
iospaces(pp, ct);
if(feature&0x10)
irq(pp, ct);
- switch(feature&0x3){
+ switch((feature>>5)&0x3){
case 1:
memspace(pp, 0, 2, 0);
break;
M pc/main.c => pc/main.c +1 -1
@@ 59,8 59,8 @@ main(void)
kbdinit();
procinit0();
initseg();
- links();
printcpufreq();
+ links();
chandevreset();
swapinit();
userinit();
M pc/scsi.c => pc/scsi.c +22 -6
@@ 12,8 12,14 @@ enum {
Ninq = 255,
Nscratch = 255,
+ CMDtest = 0x00,
CMDreqsense = 0x03,
+ CMDread6 = 0x08,
+ CMDwrite6 = 0x0A,
CMDinquire = 0x12,
+ CMDstart = 0x1B,
+ CMDread10 = 0x28,
+ CMDwrite10 = 0x2A,
};
typedef struct {
@@ 142,14 148,12 @@ scsiprobe(Ctlr *ctlr)
}
/*
- * Inquire to find out what the device is
+ * Inquire to find out what the device is.
* Drivers then use the result to attach to targets
*/
memset(t->inq, 0, Ninq);
- cmd[0] = CMDinquire;
- cmd[4] = Ninq;
nbytes = Ninq;
- s = scsiexec(t, SCSIread, cmd, sizeof(cmd), t->inq, &nbytes);
+ s = scsiinquiry(t, 0, t->inq, &nbytes);
if(s < 0) {
print("scsi%d: unit %d inquire failed, status %d\n", t->ctlrno, i, s);
continue;
@@ 196,7 200,7 @@ scsiinv(int devno, int type, Target **rt, uchar **inq, char *id)
t = &scsi[ctlr]->target[unit];
devno++;
- if(t->ok && (t->inq[0]&0x0F) == type){
+ if(t->ok && (t->inq[0]&0x1F) == type){
*rt = t;
*inq = t->inq;
sprint(id, "scsi%d: unit %d", ctlr, unit);
@@ 212,13 216,25 @@ scsistart(Target *t, char lun, int s)
uchar cmd[6];
memset(cmd, 0, sizeof cmd);
- cmd[0] = 0x1b;
+ cmd[0] = CMDstart;
cmd[1] = lun<<5;
cmd[4] = s ? 1 : 0;
return scsiexec(t, SCSIread, cmd, sizeof(cmd), 0, 0);
}
int
+scsiinquiry(Target *t, char lun, void *data, int *datalen)
+{
+ uchar cmd[6];
+
+ memset(cmd, 0, sizeof cmd);
+ cmd[0] = CMDinquire;
+ cmd[1] = lun<<5;
+ cmd[4] = *datalen;
+ return scsiexec(t, SCSIread, cmd, sizeof(cmd), data, datalen);
+}
+
+int
scsicap(Target *t, char lun, ulong *size, ulong *bsize)
{
int s, nbytes;
M pc/trap.c => pc/trap.c +1 -1
@@ 199,7 199,7 @@ trapinit(void)
/*
* Set up the second 8259 interrupt processor.
* Make 8259 interrupts start at CPU vector Int1vec.
- * Set the 8259 as master with level triggered
+ * Set the 8259 as master with edge triggered
* input with fully nested interrupts.
*/
outb(Int1ctl, (1<<4)|(1<<3)|(1<<0)); /* ICW1 - master, level triggered,
M port/devns16552.c => port/devns16552.c +9 -2
@@ 414,7 414,8 @@ ns16552kick(Uart *p)
x = splhi();
lock(&p->plock);
if(p->printing == 0 || (uartrdreg(p, Lstat) & Outready))
- if(p->cts && p->blocked == 0){
+ if(p->cts && p->blocked == 0)
+ if(p->op < p->oe || stageoutput(p)){
n = 0;
while((uartrdreg(p, Lstat) & Outready) == 0){
if(++n > 100000){
@@ 423,9 424,9 @@ ns16552kick(Uart *p)
}
}
do{
+ outb(p->port + Data, *(p->op++));
if(p->op >= p->oe && stageoutput(p) == 0)
break;
- outb(p->port + Data, *(p->op++));
}while(uartrdreg(p, Lstat) & Outready);
}
unlock(&p->plock);
@@ 813,6 814,12 @@ uartstatus(Chan *c, Uart *p, void *buf, long n, long offset)
strcat(str, " dtr");
if(tstat & Rts)
strcat(str, " rts");
+{
+int i, j;
+
+i = strlen(str);
+for(j = 0; j < 8; j++) i+=sprint(str+i, " %ux", uartrdreg(p, j));
+}
strcat(str, "\n");
return readstr(offset, buf, n, str);
}
M port/devsd.c => port/devsd.c +13 -1
@@ 87,7 87,8 @@ sdinit(void)
{
Disk *d;
ulong s, b;
- int dev, i;
+ uchar inq[255];
+ int dev, i, nbytes;
dev = 0;
for(;;) {
@@ 102,8 103,19 @@ sdinit(void)
/* Search for other lun's */
for(i = 0; i < Nlun; i++) {
d->lun = i;
+
scsireqsense(d->t, d->lun, 1);
+ /*
+ * A SCSI target does not support a lun if the
+ * the peripheral device type and qualifier fields
+ * in the response to an inquiry command are 0x7F.
+ */
+ memset(inq, 0, sizeof(inq));
+ nbytes = sizeof(inq);
+ if(scsiinquiry(d->t, d->lun, inq, &nbytes) != STok || inq[0] == 0x7F)
+ continue;
+
/* NCR Raid only seems to answer second capacity
* command if lun != 0
*/
M port/portfns.h => port/portfns.h +1 -0
@@ 239,6 239,7 @@ int scsibio(Target*, char, int, void*, long, long, long);
int scsicap(Target*, char, ulong*, ulong*);
int scsiexec(Target*, int, uchar*, int, void*, int*);
#define scsifree(p) free(p)
+int scsiinquiry(Target*, char, void*, int*);
int scsiinv(int, int, Target**, uchar**, char*);
int scsireqsense(Target*, char, int);
int scsistart(Target*, char, int);
M port/proc.c => port/proc.c +1 -0
@@ 666,6 666,7 @@ pexit(char *exitstr, int freemem)
if(exitstr && exitstr[0]){
n = sprint(wq->w.msg, "%s %d:", up->text, up->pid);
strncpy(wq->w.msg+n, exitstr, ERRLEN-n);
+ wq->w.msg[ERRLEN-1] = 0;
}
else
wq->w.msg[0] = '\0';
M port/sysproc.c => port/sysproc.c +6 -2
@@ 486,6 486,7 @@ sysexits(ulong *arg)
{
char *status;
char *inval = "invalid exit string";
+ char buf[ERRLEN];
status = (char*)arg[0];
if(status){
@@ 493,8 494,11 @@ sysexits(ulong *arg)
status = inval;
else{
validaddr((ulong)status, 1, 0);
- if(vmemchr(status, 0, ERRLEN) == 0)
- status = inval;
+ if(vmemchr(status, 0, ERRLEN) == 0){
+ memmove(buf, status, ERRLEN);
+ buf[ERRLEN-1] = 0;
+ status = buf;
+ }
}
poperror();