f834bc76d9bbee0b28f7039f8048cd64da0a1687
[b43-tools.git] / debug / libb43.py
1 """
2 #  b43 debugging library
3 #
4 #  Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
5 #
6 #  This program is free software: you can redistribute it and/or modify
7 #  it under the terms of the GNU General Public License version 3
8 #  as published by the Free Software Foundation.
9 #
10 #  This program is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #  GNU General Public License for more details.
14 #
15 #  You should have received a copy of the GNU General Public License
16 #  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 """
18
19 import sys
20 import os
21 import re
22
23
24 # SHM routing values
25 B43_SHM_UCODE           = 0
26 B43_SHM_SHARED          = 1
27 B43_SHM_REGS            = 2
28 B43_SHM_IHR             = 3
29 B43_SHM_RCMTA           = 4
30
31
32 class B43Exception(Exception):
33         pass
34
35
36 B43_MMIO_MACCTL         = 0x120
37 B43_MMIO_PSMDEBUG       = 0x154
38
39 B43_MACCTL_PSM_MACEN    = 0x00000001
40 B43_MACCTL_PSM_RUN      = 0x00000002
41 B43_MACCTL_PSM_JMP0     = 0x00000004
42 B43_MACCTL_PSM_DEBUG    = 0x00002000
43
44
45 class B43PsmDebug:
46         """Parse the contents of the PSM-debug register"""
47         def __init__(self, reg_content):
48                 self.raw = reg_content
49                 return
50
51         def getRaw(self):
52                 """Get the raw PSM-debug register value"""
53                 return self.raw
54
55         def getPc(self):
56                 """Get the microcode program counter"""
57                 return self.raw & 0xFFF
58
59
60 class B43:
61         def __init__(self, phy):
62                 debugfs_path = self.__debugfs_find()
63
64                 # Construct the debugfs b43 path to the device
65                 b43_path = debugfs_path + "/b43/"
66                 if phy:
67                         b43_path += phy
68                 else:
69                         # Get the PHY.
70                         phys = os.listdir(b43_path)
71                         if not phys:
72                                 print "Could not find any b43 device"
73                                 raise B43Exception
74                         if len(phys) != 1:
75                                 print "Found multiple b43 devices."
76                                 print "You must call this tool with a phyX parameter to specify a device"
77                                 raise B43Exception
78                         phy = phys[0]
79                         b43_path += phy;
80
81                 # Open the debugfs files
82                 try:
83                         self.f_mmio16read = file(b43_path + "/mmio16read", "r+")
84                         self.f_mmio16write = file(b43_path + "/mmio16write", "w")
85                         self.f_mmio32read = file(b43_path + "/mmio32read", "r+")
86                         self.f_mmio32write = file(b43_path + "/mmio32write", "w")
87                         self.f_shm16read = file(b43_path + "/shm16read", "r+")
88                         self.f_shm16write = file(b43_path + "/shm16write", "w")
89                         self.f_shm32read = file(b43_path + "/shm32read", "r+")
90                         self.f_shm32write = file(b43_path + "/shm32write", "w")
91                 except IOError, e:
92                         print "Could not open debugfs file %s: %s" % (e.filename, e.strerror)
93                         raise B43Exception
94
95                 self.b43_path = b43_path
96                 return
97
98         # Get the debugfs mountpoint.
99         def __debugfs_find(self):
100                 mtab = file("/etc/mtab").read().splitlines()
101                 regexp = re.compile(r"^[\w\-_]+\s+([\w/\-_]+)\s+debugfs")
102                 path = None
103                 for line in mtab:
104                         m = regexp.match(line)
105                         if m:
106                                 path = m.group(1)
107                                 break
108                 if not path:
109                         print "Could not find debugfs in /etc/mtab"
110                         raise B43Exception
111                 return path
112
113         def read16(self, reg):
114                 """Do a 16bit MMIO read"""
115                 try:
116                         self.f_mmio16read.seek(0)
117                         self.f_mmio16read.write("0x%X" % reg)
118                         self.f_mmio16read.flush()
119                         self.f_mmio16read.seek(0)
120                         val = self.f_mmio16read.read()
121                 except IOError, e:
122                         print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
123                         raise B43Exception
124                 return int(val, 16)
125
126         def read32(self, reg):
127                 """Do a 32bit MMIO read"""
128                 try:
129                         self.f_mmio32read.seek(0)
130                         self.f_mmio32read.write("0x%X" % reg)
131                         self.f_mmio32read.flush()
132                         self.f_mmio32read.seek(0)
133                         val = self.f_mmio32read.read()
134                 except IOError, e:
135                         print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
136                         raise B43Exception
137                 return int(val, 16)
138
139         def maskSet16(self, reg, mask, set):
140                 """Do a 16bit MMIO mask-and-set operation"""
141                 try:
142                         mask &= 0xFFFF
143                         set &= 0xFFFF
144                         self.f_mmio16write.seek(0)
145                         self.f_mmio16write.write("0x%X 0x%X 0x%X" % (reg, mask, set))
146                         self.f_mmio16write.flush()
147                 except IOError, e:
148                         print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
149                         raise B43Exception
150                 return
151         
152         def write16(self, reg, value):
153                 """Do a 16bit MMIO write"""
154                 self.maskSet16(reg, 0, value)
155                 return
156
157         def maskSet32(self, reg, mask, set):
158                 """Do a 32bit MMIO mask-and-set operation"""
159                 try:
160                         mask &= 0xFFFFFFFF
161                         set &= 0xFFFFFFFF
162                         self.f_mmio32write.seek(0)
163                         self.f_mmio32write.write("0x%X 0x%X 0x%X" % (reg, mask, set))
164                         self.f_mmio32write.flush()
165                 except IOError, e:
166                         print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
167                         raise B43Exception
168                 return
169
170         def write32(self, reg, value):
171                 """Do a 32bit MMIO write"""
172                 self.maskSet32(reg, 0, value)
173                 return
174
175         def shmRead16(self, routing, offset):
176                 """Do a 16bit SHM read"""
177                 try:
178                         self.f_shm16read.seek(0)
179                         self.f_shm16read.write("0x%X 0x%X" % (routing, offset))
180                         self.f_shm16read.flush()
181                         self.f_shm16read.seek(0)
182                         val = self.f_shm16read.read()
183                 except IOError, e:
184                         print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
185                         raise B43Exception
186                 return int(val, 16)
187
188         def shmMaskSet16(self, routing, offset, mask, set):
189                 """Do a 16bit SHM mask-and-set operation"""
190                 try:
191                         mask &= 0xFFFF
192                         set &= 0xFFFF
193                         self.f_shm16write.seek(0)
194                         self.f_shm16write.write("0x%X 0x%X 0x%X 0x%X" % (routing, offset, mask, set))
195                         self.f_shm16write.flush()
196                 except IOError, e:
197                         print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
198                         raise B43Exception
199                 return
200
201         def shmWrite16(self, routing, offset, value):
202                 """Do a 16bit SHM write"""
203                 self.shmMaskSet16(routing, offset, 0, value)
204                 return
205
206         def shmRead32(self, routing, offset):
207                 """Do a 32bit SHM read"""
208                 try:
209                         self.f_shm32read.seek(0)
210                         self.f_shm32read.write("0x%X 0x%X" % (routing, offset))
211                         self.f_shm32read.flush()
212                         self.f_shm32read.seek(0)
213                         val = self.f_shm32read.read()
214                 except IOError, e:
215                         print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
216                         raise B43Exception
217                 return int(val, 16)
218
219         def shmMaskSet32(self, routing, offset, mask, set):
220                 """Do a 32bit SHM mask-and-set operation"""
221                 try:
222                         mask &= 0xFFFFFFFF
223                         set &= 0xFFFFFFFF
224                         self.f_shm32write.seek(0)
225                         self.f_shm32write.write("0x%X 0x%X 0x%X 0x%X" % (routing, offset, mask, set))
226                         self.f_shm32write.flush()
227                 except IOError, e:
228                         print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
229                         raise B43Exception
230                 return
231
232         def shmWrite32(self, routing, offset, value):
233                 """Do a 32bit SHM write"""
234                 self.shmMaskSet32(routing, offset, 0, value)
235                 return
236
237         def getGprs(self):
238                 """Returns an array of 64 ints. One for each General Purpose register."""
239                 ret = []
240                 for i in range(0, 64):
241                         val = self.shmRead16(B43_SHM_REGS, i)
242                         ret.append(val)
243                 return ret
244
245         def getLinkRegs(self):
246                 """Returns an array of 4 ints. One for each Link Register."""
247                 ret = []
248                 for i in range(0, 4):
249                         val = self.read16(0x4D0 + (i * 2))
250                         ret.append(val)
251                 return ret
252
253         def getOffsetRegs(self):
254                 """Returns an array of 7 ints. One for each Offset Register."""
255                 ret = []
256                 for i in range(0, 7):
257                         val = self.read16(0x4C0 + (i * 2))
258                         ret.append(val)
259                 return ret
260
261         def shmSharedRead(self):
262                 """Returns a string containing the SHM contents."""
263                 ret = ""
264                 for i in range(0, 4096, 4):
265                         val = self.shmRead32(B43_SHM_SHARED, i)
266                         ret += "%c%c%c%c" %     (val & 0xFF,
267                                                  (val >> 8) & 0xFF,
268                                                  (val >> 16) & 0xFF,
269                                                  (val >> 24) & 0xFF)
270                 return ret
271
272         def getPsmDebug(self):
273                 """Read the PSM-debug register and return an instance of B43PsmDebug."""
274                 val = self.read32(B43_MMIO_PSMDEBUG)
275                 return B43PsmDebug(val)
276
277         def getPsmConditions(self):
278                 """This returns the contents of the programmable-PSM-conditions register."""
279                 return self.read16(0x4D8)
280
281         def ucodeStop(self):
282                 """Unconditionally stop the microcode PSM. """
283                 self.maskSet32(B43_MMIO_MACCTL, ~B43_MACCTL_PSM_RUN, 0)
284                 return
285
286         def ucodeStart(self):
287                 """Unconditionally start the microcode PSM. This will restart the
288                 microcode on the current PC. It will not jump to 0. Warning: This will
289                 unconditionally restart the PSM and ignore any driver-state!"""
290                 self.maskSet32(B43_MMIO_MACCTL, ~0, B43_MACCTL_PSM_RUN)
291                 return
292