msi.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "io.h"
  15. #include "apic.h"
  16. enum {
  17. Dpcicap = 1<<0,
  18. Dmsicap = 1<<1,
  19. Dvec = 1<<2,
  20. Debug = 0,
  21. };
  22. enum {
  23. /* address */
  24. Msiabase = 0xfee00000u,
  25. Msiadest = 1<<12, /* same as 63:56 of apic vector */
  26. Msiaedest = 1<<4, /* same as 55:48 of apic vector */
  27. Msialowpri = 1<<3, /* redirection hint */
  28. Msialogical = 1<<2,
  29. /* data */
  30. Msidlevel = 1<<15,
  31. Msidassert = 1<<14,
  32. Msidlogical = 1<<11,
  33. Msidmode = 1<<8, /* 3 bits; delivery mode */
  34. Msidvector = 0xff<<0,
  35. };
  36. enum{
  37. /* msi capabilities */
  38. Vmask = 1<<8,
  39. Cap64 = 1<<7,
  40. Mmesgmsk = 7<<4,
  41. Mmcap = 7<<1,
  42. Msienable = 1<<0,
  43. };
  44. static int
  45. msicap(Pcidev *p)
  46. {
  47. int c;
  48. c = pcicap(p, PciCapMSI);
  49. if(c == -1)
  50. return 0;
  51. return c;
  52. }
  53. static int
  54. blacklist(Pcidev *p)
  55. {
  56. switch(p->vid<<16 | p->did){
  57. case 0x11ab<<16 | 0x6485:
  58. return -1;
  59. }
  60. return 0;
  61. }
  62. int
  63. pcimsienable(Pcidev *p, uint64_t vec)
  64. {
  65. uint c, f, d, datao, lopri, dmode, logical;
  66. c = msicap(p);
  67. if(c == 0)
  68. return -1;
  69. f = pcicfgr16(p, c + 2) & ~Mmesgmsk;
  70. if(blacklist(p) != 0)
  71. return -1;
  72. datao = 8;
  73. d = vec>>48;
  74. lopri = (vec & 0x700) == MTlp;
  75. logical = (vec & Lm) != 0;
  76. pcicfgw32(p, c + 4, Msiabase | Msiaedest * d
  77. | Msialowpri * lopri | Msialogical * logical);
  78. if(f & Cap64){
  79. datao += 4;
  80. pcicfgw32(p, c + 8, 0);
  81. }
  82. dmode = (vec >> 8) & 7;
  83. pcicfgw16(p, c + datao, Msidassert | Msidlogical * logical
  84. | Msidmode * dmode | (uint)vec & 0xff);
  85. if(f & Vmask)
  86. pcicfgw32(p, c + datao + 4, 0);
  87. /* leave vectors configured but disabled for debugging */
  88. // no longer. if((s = getconf("*nomsi")) != nil && atoi(s) != 0)
  89. //return -1;
  90. pcicfgw16(p, c + 2, f);
  91. return 0;
  92. }
  93. int
  94. pcimsimask(Pcidev *p, int mask)
  95. {
  96. uint c, f;
  97. c = msicap(p);
  98. if(c == 0)
  99. return -1;
  100. f = pcicfgr16(p, c + 2) & ~Msienable;
  101. if(mask){
  102. pcicfgw16(p, c + 2, f & ~Msienable);
  103. // pciclrbme(p); cheeze
  104. }else{
  105. pcisetbme(p);
  106. pcicfgw16(p, c + 2, f | Msienable);
  107. }
  108. return 0;
  109. }