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)
317 i = gbit16(id + 106);
320 if((i & (1<<12)) && (sw = gbit32(id + 117)) >= 256)
323 f->physshift = i & 7;
324 if((pa = gbit16(id + 209)) & 0x4000)
325 f->physalign = pa & 0x3fff;
331 idwwn(Sfis*, ushort *id)
336 if(id[108]>>12 == 5){
337 u |= (uvlong)gbit16(id + 108) << 48;
338 u |= (uvlong)gbit16(id + 109) << 32;
339 u |= gbit16(id + 110) << 16;
340 u |= gbit16(id + 111) << 0;
346 idmove(char *p, ushort *u, int n)
353 for(i = 0; i < n; i += 2){
358 while(p > op && *--p == ' ')
364 memmove(op, p, n - (e - p));
368 pflag(char *s, char *e, Sfis *f)
373 for(i = 0; i < Dnflag; i++)
375 s = seprint(s, e, "%s ", flagname[i]);
376 return seprint(s, e, "\n");
380 atapirwfis(Sfis *f, uchar *c, uchar *cdb, int cdblen, int ndata)
384 fill = f->feat&Datapi16? 16: 12;
385 if((len = cdblen) > fill)
387 memmove(c + 0x40, cdb, len);
388 memset(c + 0x40 + len, 0, fill - len);
394 c[Ffeat] = 1; /* dma */
396 c[Ffeat] = 0; /* features (exp); */
399 c[Flba16] = ndata >> 8;
401 memset(c + 8, 0, Fissize - 8);
406 rwfis(Sfis *f, uchar *c, int rw, int nsect, uvlong lba)
408 uchar acmd, llba, udma;
409 static uchar tab[2][2][2] = { 0x20, 0x24, 0x30, 0x34, 0xc8, 0x25, 0xca, 0x35, };
410 static uchar ptab[2][2][2] = {
411 Pin|Ppio|P28, Pin|Ppio|P48,
412 Pout|Ppio|P28, Pout|Ppio|P48,
413 Pin|Pdma|P28, Pin|Pdma|P48,
414 Pout|Pdma|P28, Pout|Pdma|P48,
417 udma = f->udma != 0xff;
418 llba = (f->feat & Dllba) != 0;
419 acmd = tab[udma][rw][llba];
428 c[Flba16] = lba >> 16;
429 c[Fdev] = Ataobs | Atalba;
431 c[Fdev] |= (lba>>24) & 0xf;
433 c[Flba24] = lba >> 24;
434 c[Flba32] = lba >> 32;
435 c[Flba40] = lba >> 48;
439 c[Fsc8] = nsect >> 8;
443 memset(c + 16, 0, Fissize - 16);
444 return ptab[udma][rw][llba];
448 fisrw(Sfis *, uchar *c, int *n)
453 lba |= c[Flba8] << 8;
454 lba |= c[Flba16] << 16;
455 lba |= c[Flba24] << 24;
456 lba |= (uvlong)(c[Flba32] | c[Flba40]<<8) << 32;
465 sigtofis(Sfis *f, uchar *c)
470 memset(c, 0, Fissize);
485 return u[Fsc] | u[Flba0]<<8 | u[Flba8]<<16 | u[Flba16]<<24;
491 smpskelframe(Cfis *f, uchar *c, int m)
493 memset(c, 0, Fissize);
497 c[Flba32] = f->phyid;
503 uint poly, msb, l, r;
509 for(m = 1ull<<63; m > 0; m >>= 1){
522 sasbhash(uchar *t, uchar *s)
524 uint poly, msb, l, r, i, j;
529 for(i = 0; i < 8; i++)
530 for(j = 0x80; j != 0; j >>= 1){