2 * sata fises and sas frames
3 * copyright © 2009-2010 erik quanstrom
9 static char *flagname[9] = {
22 * ata8 standard (llba) cmd layout
41 * sata fis layout for fistype 0x27: host-to-device:
47 * 4 sector lba low 7:0
48 * 5 cyl low lba mid 15:8
49 * 6 cyl hi lba hi 23:16
52 * 9 cy low e lba 39:32
53 * 10 cy hi e lba 48:40
56 * 13 sector count (exp)
62 setfissig(Sfis *x, uint sig)
70 memset(c, 0, Fissize);
77 nopfis(Sfis*, uchar *c, int srst)
89 txmodefis(Sfis *f, uchar *c, uchar d)
94 if((f->sig >> 16) == 0xeb14)
103 c[Ffeat] = 3; /* set transfer mode */
104 c[Fsc] = m | d; /* sector count */
109 featfis(Sfis*, uchar *c, uchar f)
118 identifyfis(Sfis *f, uchar *c)
120 static uchar tab[] = { 0xec, 0xa1, };
123 c[Fcmd] = tab[f->sig>>16 == 0xeb14];
124 return Pin|Ppio|P28|P512;
128 flushcachefis(Sfis *f, uchar *c)
130 static uchar tab[2] = {0xe7, 0xea};
131 static uchar ptab[2] = {Pnd|P28, Pnd|P48};
134 llba = (f->feat & Dllba) != 0;
172 return (uvlong)gbit32(i+4) << 32 | gbit32(a);
176 id16(ushort *id, int i)
182 id32(ushort *id, int i)
188 id64(ushort *id, int i)
193 /* acs-2 §7.18.7.4 */
194 static ushort puistab[] = {
196 0x738c, Pspinup | Pidready,
207 for(i = 0; i < nelem(puistab); i += 2)
209 return puistab[i + 1];
210 return Pidready; /* annoying cdroms */
231 idfeat(Sfis *f, ushort *id)
237 if(f->sig>>16 == 0xeb14)
240 if((i & Ilbasp) == 0){
241 if(gbit16(id + 53) & 1){
242 f->c = gbit16(id + 1);
243 f->h = gbit16(id + 3);
244 f->s = gbit16(id + 6);
246 f->c = gbit16(id + 54);
247 f->h = gbit16(id + 55);
248 f->s = gbit16(id + 56);
252 f->c = f->h = f->s = 0;
254 j = gbit16(id + 83) | gbit16(id + 86);
257 s = gbit64(id + 100);
263 if(gbit16(id + 53) & 4)
264 for(i = gbit16(id + 88) & 0x7f; i; i >>= 1)
267 if(f->feat & Datapi){
286 i = onesc(id + 222); /* sata? */
288 if(i != 0 && i >> 12 == 1 && j != 0){
291 i = gbit16(id + 78) & gbit16(id + 79);
293 * not acceptable for comreset to
294 * wipe out device configuration.
301 if(gbit16(id + 206) & 1)
308 idss(Sfis *f, ushort *id)
312 if(f->sig>>16 == 0xeb14)
316 i = gbit16(id + 106);
319 if((sw = gbit32(id + 117)) >= 256)
322 f->physshift = i & 7;
323 return f->lsectsz * (1<<f->physshift);
327 idwwn(Sfis*, ushort *id)
332 if(id[108]>>12 == 5){
333 u |= (uvlong)gbit16(id + 108) << 48;
334 u |= (uvlong)gbit16(id + 109) << 32;
335 u |= gbit16(id + 110) << 16;
336 u |= gbit16(id + 111) << 0;
342 idmove(char *p, ushort *u, int n)
349 for(i = 0; i < n; i += 2){
354 while(p > op && *--p == ' ')
360 memmove(op, p, n - (e - p));
364 pflag(char *s, char *e, Sfis *f)
369 for(i = 0; i < Dnflag; i++)
371 s = seprint(s, e, "%s ", flagname[i]);
372 return seprint(s, e, "\n");
376 atapirwfis(Sfis *f, uchar *c, uchar *cdb, int cdblen, int ndata)
380 fill = f->feat&Datapi16? 16: 12;
381 if((len = cdblen) > fill)
383 memmove(c + 0x40, cdb, len);
384 memset(c + 0x40 + len, 0, fill - len);
390 c[Ffeat] = 1; /* dma */
392 c[Ffeat] = 0; /* features (exp); */
395 c[Flba16] = ndata >> 8;
397 memset(c + 8, 0, Fissize - 8);
402 rwfis(Sfis *f, uchar *c, int rw, int nsect, uvlong lba)
404 uchar acmd, llba, udma;
405 static uchar tab[2][2][2] = { 0x20, 0x24, 0x30, 0x34, 0xc8, 0x25, 0xca, 0x35, };
406 static uchar ptab[2][2][2] = {
407 Pin|Ppio|P28, Pin|Ppio|P48,
408 Pout|Ppio|P28, Pout|Ppio|P48,
409 Pin|Pdma|P28, Pin|Pdma|P48,
410 Pout|Pdma|P28, Pout|Pdma|P48,
413 nsect >>= f->physshift;
414 lba >>= f->physshift;
416 udma = f->udma != 0xff;
417 llba = (f->feat & Dllba) != 0;
418 acmd = tab[udma][rw][llba];
427 c[Flba16] = lba >> 16;
428 c[Fdev] = Ataobs | Atalba;
430 c[Fdev] |= (lba>>24) & 0xf;
432 c[Flba24] = lba >> 24;
433 c[Flba32] = lba >> 32;
434 c[Flba40] = lba >> 48;
438 c[Fsc8] = nsect >> 8;
442 memset(c + 16, 0, Fissize - 16);
443 return ptab[udma][rw][llba];
447 fisrw(Sfis *f, uchar *c, int *n)
452 lba |= c[Flba8] << 8;
453 lba |= c[Flba16] << 16;
454 lba |= c[Flba24] << 24;
455 lba |= (uvlong)(c[Flba32] | c[Flba40]<<8) << 32;
461 lba >>= f->physshift;
467 sigtofis(Sfis *f, uchar *c)
472 memset(c, 0, Fissize);
487 return u[Fsc] | u[Flba0]<<8 | u[Flba8]<<16 | u[Flba16]<<24;
493 smpskelframe(Cfis *f, uchar *c, int m)
495 memset(c, 0, Fissize);
499 c[Flba32] = f->phyid;
505 uint poly, msb, l, r;
511 for(m = 1ull<<63; m > 0; m >>= 1){
524 sasbhash(uchar *t, uchar *s)
526 uint poly, msb, l, r, i, j;
531 for(i = 0; i < 8; i++)
532 for(j = 0x80; j != 0; j >>= 1){