kopia lustrzana https://github.com/peterhinch/micropython_eeprom
Refactor: common base class in bdevice.py
rodzic
992e35b994
commit
1c659ce333
|
@ -0,0 +1,47 @@
|
||||||
|
# bdevice.py Hardware-agnostic base class for block devices.
|
||||||
|
|
||||||
|
# Released under the MIT License (MIT). See LICENSE.
|
||||||
|
# Copyright (c) 2019 Peter Hinch
|
||||||
|
|
||||||
|
# Hardware-independent class implementing the uos.AbstractBlockDev protocol with
|
||||||
|
# simple and extended interface. It should therefore support littlefs.
|
||||||
|
# http://docs.micropython.org/en/latest/reference/filesystem.html#custom-block-devices
|
||||||
|
|
||||||
|
# The subclass must implement .readwrite which can read or write arbitrary amounts
|
||||||
|
# of data to arbitrary addresses. IOW .readwrite handles physical block structure
|
||||||
|
# while ioctl supports a virtual block size.
|
||||||
|
|
||||||
|
class BlockDevice:
|
||||||
|
|
||||||
|
def __init__(self, nbits, nchips, chip_size):
|
||||||
|
self._c_bytes = chip_size # Size of chip in bytes
|
||||||
|
self._a_bytes = chip_size * nchips # Size of array
|
||||||
|
self._nbits = nbits # Block size in bits
|
||||||
|
self._block_size = 2**nbits
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return self._a_bytes
|
||||||
|
|
||||||
|
# Handle special cases of a slice. Always return a pair of positive indices.
|
||||||
|
def do_slice(self, addr):
|
||||||
|
if not (addr.step is None or addr.step == 1):
|
||||||
|
raise NotImplementedError('only slices with step=1 (aka None) are supported')
|
||||||
|
start = addr.start if addr.start is not None else 0
|
||||||
|
stop = addr.stop if addr.stop is not None else self._a_bytes
|
||||||
|
start = start if start >= 0 else self._a_bytes + start
|
||||||
|
stop = stop if stop >= 0 else self._a_bytes + stop
|
||||||
|
return start, stop
|
||||||
|
|
||||||
|
# IOCTL protocol.
|
||||||
|
def readblocks(self, blocknum, buf, offset=0):
|
||||||
|
return self.readwrite(offset + (blocknum << self._nbits), buf, True)
|
||||||
|
|
||||||
|
def writeblocks(self, blocknum, buf, offset=0):
|
||||||
|
self.readwrite(offset + (blocknum << self._nbits), buf, False)
|
||||||
|
|
||||||
|
def ioctl(self, op, arg):
|
||||||
|
#print("ioctl(%d, %r)" % (op, arg))
|
||||||
|
if op == 4: # BP_IOCTL_SEC_COUNT
|
||||||
|
return self._a_bytes >> self._nbits
|
||||||
|
if op == 5: # BP_IOCTL_SEC_SIZE
|
||||||
|
return self._block_size
|
47
i2c/I2C.md
47
i2c/I2C.md
|
@ -69,7 +69,10 @@ Other platforms may vary.
|
||||||
# 3. Files
|
# 3. Files
|
||||||
|
|
||||||
1. `eeprom_i2c.py` Device driver.
|
1. `eeprom_i2c.py` Device driver.
|
||||||
2. `eep_i2c.py` Test programs for above.
|
2. `bdevice.py` (In root directory) Base class for the device driver.
|
||||||
|
3. `eep_i2c.py` Test programs for above.
|
||||||
|
|
||||||
|
Installation: copy files 1 and 2 (optionally 3) to the target filesystem.
|
||||||
|
|
||||||
# 4. The device driver
|
# 4. The device driver
|
||||||
|
|
||||||
|
@ -90,10 +93,10 @@ The above will reformat a drive with an existing filesystem: to mount an
|
||||||
existing filesystem simply omit the commented line.
|
existing filesystem simply omit the commented line.
|
||||||
|
|
||||||
Note that, at the outset, you need to decide whether to use the array as a
|
Note that, at the outset, you need to decide whether to use the array as a
|
||||||
mounted filesystem or as a byte array. As a filesystem the limited size is an
|
mounted filesystem or as a byte array. The filesystem is relatively small but
|
||||||
issue, but a potential use case is for pickling Python objects for example to
|
has high integrity owing to the hardware longevity. Typical use-cases involve
|
||||||
achieve persistence when issuing `pyb.standby()`; also for holding a small
|
files which are frequently updated. These include files used for storing Python
|
||||||
frequently updated persistent btree database.
|
objects serialised using Pickle/ujson or files holding a btree database.
|
||||||
|
|
||||||
The I2C bus must be instantiated using the `machine` module.
|
The I2C bus must be instantiated using the `machine` module.
|
||||||
|
|
||||||
|
@ -126,7 +129,7 @@ of single byte access:
|
||||||
```python
|
```python
|
||||||
from machine import I2C
|
from machine import I2C
|
||||||
from eeprom_i2c import EEPROM, T24C512
|
from eeprom_i2c import EEPROM, T24C512
|
||||||
eep = EEPROM(I2C(1), T24C512)
|
eep = EEPROM(I2C(2), T24C512)
|
||||||
eep[2000] = 42
|
eep[2000] = 42
|
||||||
print(eep[2000]) # Return an integer
|
print(eep[2000]) # Return an integer
|
||||||
```
|
```
|
||||||
|
@ -135,12 +138,13 @@ writing, the size of the slice must match the length of the buffer:
|
||||||
```python
|
```python
|
||||||
from machine import I2C
|
from machine import I2C
|
||||||
from eeprom_i2c import EEPROM, T24C512
|
from eeprom_i2c import EEPROM, T24C512
|
||||||
eep = EEPROM(I2C(1), T24C512)
|
eep = EEPROM(I2C(2), T24C512)
|
||||||
eep[2000:2002] = bytearray((42, 43))
|
eep[2000:2002] = bytearray((42, 43))
|
||||||
print(eep[2000:2002]) # Returns a bytearray
|
print(eep[2000:2002]) # Returns a bytearray
|
||||||
```
|
```
|
||||||
Three argument slices are not supported: any third arg will be ignored. One
|
Three argument slices are not supported: a third arg (other than 1) will cause
|
||||||
argument slices (`eep[:5]` or `eep[13100:]`) and negative args are supported.
|
an exception. One argument slices (`eep[:5]` or `eep[13100:]`) and negative
|
||||||
|
args are supported.
|
||||||
|
|
||||||
#### 4.1.2.2 readwrite
|
#### 4.1.2.2 readwrite
|
||||||
|
|
||||||
|
@ -153,23 +157,14 @@ advantage of using a pre-allocated buffer. Arguments:
|
||||||
determines the quantity of data read or written. A `RuntimeError` will be
|
determines the quantity of data read or written. A `RuntimeError` will be
|
||||||
thrown if the read or write extends beyond the end of the physical space.
|
thrown if the read or write extends beyond the end of the physical space.
|
||||||
|
|
||||||
### 4.1.3 Methods providing the block protocol
|
### 4.1.3 Other methods
|
||||||
|
|
||||||
For the protocol definition see
|
#### The len() operator
|
||||||
[the pyb documentation](http://docs.micropython.org/en/latest/library/uos.html#uos.AbstractBlockDev)
|
|
||||||
|
|
||||||
`readblocks()`
|
|
||||||
`writeblocks()`
|
|
||||||
`ioctl()`
|
|
||||||
|
|
||||||
### 4.1.4 Other methods
|
|
||||||
|
|
||||||
#### 4.1.4.1 The len() operator
|
|
||||||
|
|
||||||
The size of the EEPROM array in bytes may be retrieved by issuing `len(eep)`
|
The size of the EEPROM array in bytes may be retrieved by issuing `len(eep)`
|
||||||
where `eep` is the `EEPROM` instance.
|
where `eep` is the `EEPROM` instance.
|
||||||
|
|
||||||
#### 4.1.4.2 scan
|
#### scan
|
||||||
|
|
||||||
Scans the I2C bus and returns the number of EEPROM devices detected.
|
Scans the I2C bus and returns the number of EEPROM devices detected.
|
||||||
|
|
||||||
|
@ -177,6 +172,16 @@ Other than for debugging there is no need to call `scan()`: the constructor
|
||||||
will throw a `RuntimeError` if it fails to communicate with and correctly
|
will throw a `RuntimeError` if it fails to communicate with and correctly
|
||||||
identify the chip.
|
identify the chip.
|
||||||
|
|
||||||
|
### 4.1.4 Methods providing the block protocol
|
||||||
|
|
||||||
|
These are provided by the base class. For the protocol definition see
|
||||||
|
[the pyb documentation](http://docs.micropython.org/en/latest/library/uos.html#uos.AbstractBlockDev)
|
||||||
|
also [here](http://docs.micropython.org/en/latest/reference/filesystem.html#custom-block-devices).
|
||||||
|
|
||||||
|
`readblocks()`
|
||||||
|
`writeblocks()`
|
||||||
|
`ioctl()`
|
||||||
|
|
||||||
# 5. Test program eep_i2c.py
|
# 5. Test program eep_i2c.py
|
||||||
|
|
||||||
This assumes a Pyboard 1.x or Pyboard D with EEPROM(s) wired as above. It
|
This assumes a Pyboard 1.x or Pyboard D with EEPROM(s) wired as above. It
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from micropython import const
|
from micropython import const
|
||||||
|
from bdevice import BlockDevice
|
||||||
|
|
||||||
ADDR = const(0x50) # Base address of chip
|
ADDR = const(0x50) # Base address of chip
|
||||||
|
|
||||||
|
@ -15,27 +16,18 @@ T24C64 = const(8192) # 8KiB 64Kbits
|
||||||
|
|
||||||
# Logical EEPROM device consists of 1-8 physical chips. Chips must all be the
|
# Logical EEPROM device consists of 1-8 physical chips. Chips must all be the
|
||||||
# same size, and must have contiguous addresses starting from 0x50.
|
# same size, and must have contiguous addresses starting from 0x50.
|
||||||
class EEPROM():
|
class EEPROM(BlockDevice):
|
||||||
|
|
||||||
def __init__(self, i2c, chip_size=T24C512, verbose=True):
|
def __init__(self, i2c, chip_size=T24C512, verbose=True):
|
||||||
self._i2c = i2c
|
self._i2c = i2c
|
||||||
if chip_size not in (T24C64, T24C128, T24C256, T24C512):
|
if chip_size not in (T24C64, T24C128, T24C256, T24C512):
|
||||||
raise RuntimeError('Invalid chip size', chip_size)
|
raise RuntimeError('Invalid chip size', chip_size)
|
||||||
nchips = self.scan(verbose, chip_size) # No. of EEPROM chips
|
nchips = self.scan(verbose, chip_size) # No. of EEPROM chips
|
||||||
self._c_bytes = chip_size # Size of chip in bytes
|
super().__init__(9, nchips, chip_size)
|
||||||
self._a_bytes = chip_size * nchips # Size of array
|
|
||||||
self._i2c_addr = 0 # I2C address of current chip
|
self._i2c_addr = 0 # I2C address of current chip
|
||||||
self._buf1 = bytearray(1)
|
self._buf1 = bytearray(1)
|
||||||
self._addrbuf = bytearray(2) # Memory offset into current chip
|
self._addrbuf = bytearray(2) # Memory offset into current chip
|
||||||
|
|
||||||
# Handle special cases of a slice. Always return a pair of positive indices.
|
|
||||||
def do_slice(self, addr):
|
|
||||||
start = addr.start if addr.start is not None else 0
|
|
||||||
stop = addr.stop if addr.stop is not None else self._a_bytes
|
|
||||||
start = start if start >= 0 else self._a_bytes + start
|
|
||||||
stop = stop if stop >= 0 else self._a_bytes + stop
|
|
||||||
return start, stop
|
|
||||||
|
|
||||||
# Check for a valid hardware configuration
|
# Check for a valid hardware configuration
|
||||||
def scan(self, verbose, chip_size):
|
def scan(self, verbose, chip_size):
|
||||||
devices = self._i2c.scan() # All devices on I2C bus
|
devices = self._i2c.scan() # All devices on I2C bus
|
||||||
|
@ -50,9 +42,6 @@ class EEPROM():
|
||||||
print(s.format(nchips, chip_size * nchips))
|
print(s.format(nchips, chip_size * nchips))
|
||||||
return nchips
|
return nchips
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return self._a_bytes
|
|
||||||
|
|
||||||
def _wait_rdy(self): # After a write, wait for device to become ready
|
def _wait_rdy(self): # After a write, wait for device to become ready
|
||||||
self._buf1[0] = 0
|
self._buf1[0] = 0
|
||||||
while True:
|
while True:
|
||||||
|
@ -119,17 +108,3 @@ class EEPROM():
|
||||||
start += npage
|
start += npage
|
||||||
addr += npage
|
addr += npage
|
||||||
return buf
|
return buf
|
||||||
|
|
||||||
# IOCTL protocol. Emulate block size of 512 bytes for now.
|
|
||||||
def readblocks(self, blocknum, buf):
|
|
||||||
return self.readwrite(blocknum << 9, buf, True)
|
|
||||||
|
|
||||||
def writeblocks(self, blocknum, buf):
|
|
||||||
self.readwrite(blocknum << 9, buf, False)
|
|
||||||
|
|
||||||
def ioctl(self, op, arg):
|
|
||||||
#print("ioctl(%d, %r)" % (op, arg))
|
|
||||||
if op == 4: # BP_IOCTL_SEC_COUNT
|
|
||||||
return self._a_bytes >> 9
|
|
||||||
if op == 5: # BP_IOCTL_SEC_SIZE
|
|
||||||
return 512
|
|
||||||
|
|
45
spi/SPI.md
45
spi/SPI.md
|
@ -46,7 +46,10 @@ Other platforms may vary.
|
||||||
# 3. Files
|
# 3. Files
|
||||||
|
|
||||||
1. `eeprom_spi.py` Device driver.
|
1. `eeprom_spi.py` Device driver.
|
||||||
2. `eep_spi.py` Test programs for above.
|
2. `bdevice.py` (In root directory) Base class for the device driver.
|
||||||
|
3. `eep_spi.py` Test programs for above.
|
||||||
|
|
||||||
|
Installation: copy files 1 and 2 (optionally 3) to the target filesystem.
|
||||||
|
|
||||||
# 4. The device driver
|
# 4. The device driver
|
||||||
|
|
||||||
|
@ -68,10 +71,10 @@ The above will reformat a drive with an existing filesystem: to mount an
|
||||||
existing filesystem simply omit the commented line.
|
existing filesystem simply omit the commented line.
|
||||||
|
|
||||||
Note that, at the outset, you need to decide whether to use the array as a
|
Note that, at the outset, you need to decide whether to use the array as a
|
||||||
mounted filesystem or as a byte array. As a filesystem the limited size is an
|
mounted filesystem or as a byte array. The filesystem is relatively small but
|
||||||
issue, but a potential use case is for pickling Python objects for example to
|
has high integrity owing to the hardware longevity. Typical use-cases involve
|
||||||
achieve persistence when issuing `pyb.standby()`; also for holding a small
|
files which are frequently updated. These include files used for storing Python
|
||||||
frequently updated persistent btree database.
|
objects serialised using Pickle/ujson or files holding a btree database.
|
||||||
|
|
||||||
The SPI bus must be instantiated using the `machine` module.
|
The SPI bus must be instantiated using the `machine` module.
|
||||||
|
|
||||||
|
@ -125,8 +128,9 @@ eep = EEPROM(SPI(2, baudrate=20_000_000), cspins)
|
||||||
eep[2000:2002] = bytearray((42, 43))
|
eep[2000:2002] = bytearray((42, 43))
|
||||||
print(eep[2000:2002]) # Returns a bytearray
|
print(eep[2000:2002]) # Returns a bytearray
|
||||||
```
|
```
|
||||||
Three argument slices are not supported: any third arg will be ignored. One
|
Three argument slices are not supported: a third arg (other than 1) will cause
|
||||||
argument slices (`eep[:5]` or `eep[13100:]`) and negative args are supported.
|
an exception. One argument slices (`eep[:5]` or `eep[13100:]`) and negative
|
||||||
|
args are supported.
|
||||||
|
|
||||||
#### 4.1.2.2 readwrite
|
#### 4.1.2.2 readwrite
|
||||||
|
|
||||||
|
@ -139,23 +143,14 @@ advantage of using a pre-allocated buffer. Arguments:
|
||||||
determines the quantity of data read or written. A `RuntimeError` will be
|
determines the quantity of data read or written. A `RuntimeError` will be
|
||||||
thrown if the read or write extends beyond the end of the physical space.
|
thrown if the read or write extends beyond the end of the physical space.
|
||||||
|
|
||||||
### 4.1.3 Methods providing the block protocol
|
### 4.1.3 Other methods
|
||||||
|
|
||||||
For the protocol definition see
|
#### The len() operator
|
||||||
[the pyb documentation](http://docs.micropython.org/en/latest/library/uos.html#uos.AbstractBlockDev)
|
|
||||||
|
|
||||||
`readblocks()`
|
|
||||||
`writeblocks()`
|
|
||||||
`ioctl()`
|
|
||||||
|
|
||||||
### 4.1.4 Other methods
|
|
||||||
|
|
||||||
#### 4.1.4.1 The len() operator
|
|
||||||
|
|
||||||
The size of the EEPROM array in bytes may be retrieved by issuing `len(eep)`
|
The size of the EEPROM array in bytes may be retrieved by issuing `len(eep)`
|
||||||
where `eep` is the `EEPROM` instance.
|
where `eep` is the `EEPROM` instance.
|
||||||
|
|
||||||
#### 4.1.4.2 scan
|
#### scan
|
||||||
|
|
||||||
Activate each chip select in turn checking for a valid device and returns the
|
Activate each chip select in turn checking for a valid device and returns the
|
||||||
number of EEPROM devices detected. A `RuntimeError` will be raised if any CS
|
number of EEPROM devices detected. A `RuntimeError` will be raised if any CS
|
||||||
|
@ -165,10 +160,20 @@ Other than for debugging there is no need to call `scan()`: the constructor
|
||||||
will throw a `RuntimeError` if it fails to communicate with and correctly
|
will throw a `RuntimeError` if it fails to communicate with and correctly
|
||||||
identify the chip.
|
identify the chip.
|
||||||
|
|
||||||
#### 4.1.4.3 erase
|
#### erase
|
||||||
|
|
||||||
Erases the entire array.
|
Erases the entire array.
|
||||||
|
|
||||||
|
### 4.1.4 Methods providing the block protocol
|
||||||
|
|
||||||
|
These are provided by the base class. For the protocol definition see
|
||||||
|
[the pyb documentation](http://docs.micropython.org/en/latest/library/uos.html#uos.AbstractBlockDev)
|
||||||
|
also [here](http://docs.micropython.org/en/latest/reference/filesystem.html#custom-block-devices).
|
||||||
|
|
||||||
|
`readblocks()`
|
||||||
|
`writeblocks()`
|
||||||
|
`ioctl()`
|
||||||
|
|
||||||
# 5. Test program eep_spi.py
|
# 5. Test program eep_spi.py
|
||||||
|
|
||||||
This assumes a Pyboard 1.x or Pyboard D with EEPROM(s) wired as above. It
|
This assumes a Pyboard 1.x or Pyboard D with EEPROM(s) wired as above. It
|
||||||
|
|
|
@ -6,42 +6,33 @@
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from micropython import const
|
from micropython import const
|
||||||
|
from bdevice import BlockDevice
|
||||||
|
|
||||||
_SIZE = const(131072) # Chip size 128KiB
|
_SIZE = const(131072) # Chip size 128KiB
|
||||||
# Supported instruction set
|
# Supported instruction set
|
||||||
_READ = const(3)
|
_READ = const(3)
|
||||||
_WRITE = const(2)
|
_WRITE = const(2)
|
||||||
_WREN = const(6)
|
_WREN = const(6) # Write enable
|
||||||
_WRDI = const(4)
|
_RDSR = const(5) # Read status register
|
||||||
_RDSR = const(5)
|
_RDID = const(0xab) # Read chip ID
|
||||||
_WRSR = const(1)
|
_CE = const(0xc7) # Chip erase
|
||||||
_RDID = const(0xab)
|
# Not implemented: Write disable and Write status register
|
||||||
_CE = const(0xc7)
|
# _WRDI = const(4)
|
||||||
|
# _WRSR = const(1)
|
||||||
|
|
||||||
# Logical EEPROM device consisting of an arbitrary number of physical chips
|
# Logical EEPROM device comprising one or more physical chips sharing an SPI bus.
|
||||||
# sharing an SPI bus.
|
class EEPROM(BlockDevice):
|
||||||
class EEPROM():
|
|
||||||
|
|
||||||
def __init__(self, spi, cspins, verbose=True):
|
def __init__(self, spi, cspins, verbose=True):
|
||||||
|
# args: virtual block size in bits, no. of chips, bytes in each chip
|
||||||
|
super().__init__(9, len(cspins), _SIZE)
|
||||||
self._spi = spi
|
self._spi = spi
|
||||||
self._cspins = cspins
|
self._cspins = cspins
|
||||||
nchips = len(cspins) # No. of EEPROM chips
|
|
||||||
# size as a bound variable for future bigger chips
|
|
||||||
self._c_bytes = _SIZE # Size of chip in bytes
|
|
||||||
self._a_bytes = _SIZE * nchips # Size of array
|
|
||||||
self._ccs = None # Chip select Pin object for current chip
|
self._ccs = None # Chip select Pin object for current chip
|
||||||
self._bufp = bytearray(5) # instruction + 3 byte address + 1 byte value
|
self._bufp = bytearray(5) # instruction + 3 byte address + 1 byte value
|
||||||
self._mvp = memoryview(self._bufp) # cost-free slicing
|
self._mvp = memoryview(self._bufp) # cost-free slicing
|
||||||
self.scan(verbose)
|
self.scan(verbose)
|
||||||
|
|
||||||
# Handle special cases of a slice. Always return a pair of positive indices.
|
|
||||||
def do_slice(self, addr):
|
|
||||||
start = addr.start if addr.start is not None else 0
|
|
||||||
stop = addr.stop if addr.stop is not None else self._a_bytes
|
|
||||||
start = start if start >= 0 else self._a_bytes + start
|
|
||||||
stop = stop if stop >= 0 else self._a_bytes + stop
|
|
||||||
return start, stop
|
|
||||||
|
|
||||||
# Check for a valid hardware configuration
|
# Check for a valid hardware configuration
|
||||||
def scan(self, verbose):
|
def scan(self, verbose):
|
||||||
mvp = self._mvp
|
mvp = self._mvp
|
||||||
|
@ -70,9 +61,6 @@ class EEPROM():
|
||||||
cs(1)
|
cs(1)
|
||||||
self._wait_rdy() # Wait for erase to complete
|
self._wait_rdy() # Wait for erase to complete
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return self._a_bytes
|
|
||||||
|
|
||||||
def _wait_rdy(self): # After a write, wait for device to become ready
|
def _wait_rdy(self): # After a write, wait for device to become ready
|
||||||
mvp = self._mvp
|
mvp = self._mvp
|
||||||
cs = self._ccs # Chip is already current
|
cs = self._ccs # Chip is already current
|
||||||
|
@ -81,8 +69,7 @@ class EEPROM():
|
||||||
cs(0)
|
cs(0)
|
||||||
self._spi.write_readinto(mvp[:2], mvp[:2])
|
self._spi.write_readinto(mvp[:2], mvp[:2])
|
||||||
cs(1)
|
cs(1)
|
||||||
assert not mvp[1] & 0xC # BP0, BP1 assumed 0
|
if not mvp[1]: # We never set BP0 or BP1 so ready state is 0.
|
||||||
if not (mvp[1] & 1):
|
|
||||||
break
|
break
|
||||||
time.sleep_ms(1)
|
time.sleep_ms(1)
|
||||||
|
|
||||||
|
@ -169,17 +156,3 @@ class EEPROM():
|
||||||
start += npage
|
start += npage
|
||||||
addr += npage
|
addr += npage
|
||||||
return buf
|
return buf
|
||||||
|
|
||||||
# IOCTL protocol. Emulate block size of 512 bytes.
|
|
||||||
def readblocks(self, blocknum, buf):
|
|
||||||
return self.readwrite(blocknum << 9, buf, True)
|
|
||||||
|
|
||||||
def writeblocks(self, blocknum, buf):
|
|
||||||
self.readwrite(blocknum << 9, buf, False)
|
|
||||||
|
|
||||||
def ioctl(self, op, arg):
|
|
||||||
#print("ioctl(%d, %r)" % (op, arg))
|
|
||||||
if op == 4: # BP_IOCTL_SEC_COUNT
|
|
||||||
return self._a_bytes >> 9
|
|
||||||
if op == 5: # BP_IOCTL_SEC_SIZE
|
|
||||||
return 512
|
|
||||||
|
|
Ładowanie…
Reference in New Issue