gem5  v20.1.0.0
ide_disk.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2004-2005 The Regents of The University of Michigan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  */
40 
45 #ifndef __DEV_STORAGE_IDE_DISK_HH__
46 #define __DEV_STORAGE_IDE_DISK_HH__
47 
48 #include "base/statistics.hh"
49 #include "dev/io_device.hh"
51 #include "dev/storage/ide_atareg.h"
52 #include "dev/storage/ide_ctrl.hh"
53 #include "dev/storage/ide_wdcreg.h"
54 #include "params/IdeDisk.hh"
55 #include "sim/eventq.hh"
56 
57 class ChunkGenerator;
58 
59 #define DMA_BACKOFF_PERIOD 200
60 
61 #define MAX_DMA_SIZE 0x20000 // 128K
62 #define MAX_SINGLE_DMA_SIZE 0x10000
63 #define MAX_MULTSECT (128)
64 
65 #define PRD_BASE_MASK 0xfffffffe
66 #define PRD_COUNT_MASK 0xfffe
67 #define PRD_EOT_MASK 0x8000
68 
69 typedef struct PrdEntry {
70  uint32_t baseAddr;
71  uint16_t byteCount;
72  uint16_t endOfTable;
73 } PrdEntry_t;
74 
76  public:
78 
79  uint32_t getBaseAddr()
80  {
81  return (entry.baseAddr & PRD_BASE_MASK);
82  }
83 
84  uint32_t getByteCount()
85  {
86  return ((entry.byteCount == 0) ? MAX_SINGLE_DMA_SIZE :
88  }
89 
90  uint16_t getEOT()
91  {
92  return (entry.endOfTable & PRD_EOT_MASK);
93  }
94 };
95 
96 #define DATA_OFFSET (0)
97 #define ERROR_OFFSET (1)
98 #define FEATURES_OFFSET (1)
99 #define NSECTOR_OFFSET (2)
100 #define SECTOR_OFFSET (3)
101 #define LCYL_OFFSET (4)
102 #define HCYL_OFFSET (5)
103 #define SELECT_OFFSET (6)
104 #define DRIVE_OFFSET (6)
105 #define STATUS_OFFSET (7)
106 #define COMMAND_OFFSET (7)
107 
108 #define CONTROL_OFFSET (2)
109 #define ALTSTAT_OFFSET (2)
110 
111 #define SELECT_DEV_BIT 0x10
112 #define CONTROL_RST_BIT 0x04
113 #define CONTROL_IEN_BIT 0x02
114 #define STATUS_BSY_BIT 0x80
115 #define STATUS_DRDY_BIT 0x40
116 #define STATUS_DRQ_BIT 0x08
117 #define STATUS_SEEK_BIT 0x10
118 #define STATUS_DF_BIT 0x20
119 #define DRIVE_LBA_BIT 0x40
120 
121 #define DEV0 (0)
122 #define DEV1 (1)
123 
124 typedef struct CommandReg {
125  uint16_t data;
126  uint8_t error;
127  uint8_t sec_count;
128  uint8_t sec_num;
129  uint8_t cyl_low;
130  uint8_t cyl_high;
131  union {
132  uint8_t drive;
133  uint8_t head;
134  };
135  uint8_t command;
136 } CommandReg_t;
137 
138 typedef enum Events {
139  None = 0,
146 } Events_t;
147 
148 typedef enum DevAction {
149  ACT_NONE = 0,
164 } DevAction_t;
165 
166 typedef enum DevState {
167  // Device idle
171 
172  // Software reset
174 
175  // Non-data commands
177 
178  // PIO data-in (data to host)
182 
183  // PIO data-out (data from host)
187 
188  // DMA protocol
192 } DevState_t;
193 
194 typedef enum DmaState {
195  Dma_Idle = 0,
198 } DmaState_t;
199 
200 class IdeController;
201 
205 class IdeDisk : public SimObject
206 {
207  protected:
212 
213  protected:
216 
217  private:
221  uint8_t *dataBuffer;
223  uint32_t cmdBytes;
225  uint32_t cmdBytesLeft;
227  uint32_t drqBytesLeft;
229  uint32_t curSector;
233  uint8_t status;
235  bool nIENBit;
241  bool dmaRead;
245  uint32_t curPrdAddr;
249  int devID;
254 
261 
262  public:
263  typedef IdeDiskParams Params;
264  IdeDisk(const Params *p);
265 
269  ~IdeDisk();
270 
274  void reset(int id);
275 
279  void regStats() override;
280 
285  void
287  {
288  panic_if(ctrl, "Cannot change the controller once set!\n");
289  ctrl = c;
290  pageBytes = page_bytes;
291  }
292 
293  // Device register read/write
294  void readCommand(const Addr offset, int size, uint8_t *data);
295  void readControl(const Addr offset, int size, uint8_t *data);
296  void writeCommand(const Addr offset, int size, const uint8_t *data);
297  void writeControl(const Addr offset, int size, const uint8_t *data);
298 
299  // Start/abort functions
300  void startDma(const uint32_t &prdTableBase);
301  void abortDma();
302 
303  private:
304  void startCommand();
305 
306  // Interrupt management
307  void intrPost();
308  void intrClear();
309 
310  // DMA stuff
311  void doDmaTransfer();
313 
314  void doDmaDataRead();
315 
316  void doDmaRead();
319 
320  void doDmaDataWrite();
321 
322  void doDmaWrite();
325 
326  void dmaPrdReadDone();
328 
329  void dmaReadDone();
331 
332  void dmaWriteDone();
334 
335  // Disk image read/write
336  void readDisk(uint32_t sector, uint8_t *data);
337  void writeDisk(uint32_t sector, uint8_t *data);
338 
339  // State machine management
340  void updateState(DevAction_t action);
341 
342  // Utility functions
343  bool isBSYSet() { return (status & STATUS_BSY_BIT); }
344  bool isIENSet() { return nIENBit; }
345  bool isDEVSelect();
346 
347  void setComplete()
348  {
349  // clear out the status byte
350  status = 0;
351  // set the DRDY bit
353  // set the SEEK bit
355  }
356 
357  uint32_t getLBABase()
358  {
359  return (Addr)(((cmdReg.head & 0xf) << 24) | (cmdReg.cyl_high << 16) |
360  (cmdReg.cyl_low << 8) | (cmdReg.sec_num));
361  }
362 
363  inline Addr pciToDma(Addr pciAddr);
364 
365  void serialize(CheckpointOut &cp) const override;
366  void unserialize(CheckpointIn &cp) override;
367 };
368 
369 
370 #endif // __DEV_STORAGE_IDE_DISK_HH__
IdeDisk::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: ide_disk.cc:1071
IdeDisk::dmaReadBytes
Stats::Scalar dmaReadBytes
Definition: ide_disk.hh:256
Prepare_Data_In
@ Prepare_Data_In
Definition: ide_disk.hh:179
ACT_DMA_READY
@ ACT_DMA_READY
Definition: ide_disk.hh:160
io_device.hh
IdeDisk::getLBABase
uint32_t getLBABase()
Definition: ide_disk.hh:357
IdeDisk::curPrdAddr
uint32_t curPrdAddr
PRD table base address.
Definition: ide_disk.hh:245
DmaWrite
@ DmaWrite
Definition: ide_disk.hh:145
DmaState
DmaState
Definition: ide_disk.hh:194
CommandReg::head
uint8_t head
Definition: ide_disk.hh:133
data
const char data[]
Definition: circlebuf.test.cc:42
IdeDisk::status
uint8_t status
Status register.
Definition: ide_disk.hh:233
PrdTableEntry::getBaseAddr
uint32_t getBaseAddr()
Definition: ide_disk.hh:79
Events_t
enum Events Events_t
IdeController
Device model for an Intel PIIX4 IDE controller.
Definition: ide_ctrl.hh:48
CommandReg::error
uint8_t error
Definition: ide_disk.hh:126
PrdEntry::endOfTable
uint16_t endOfTable
Definition: ide_disk.hh:72
IdeDisk::dmaPrdReadEvent
EventFunctionWrapper dmaPrdReadEvent
Definition: ide_disk.hh:327
IdeDisk::~IdeDisk
~IdeDisk()
Delete the data buffer.
Definition: ide_disk.cc:135
Transfer
@ Transfer
Definition: ide_disk.hh:140
ACT_SRST_SET
@ ACT_SRST_SET
Definition: ide_disk.hh:162
IdeDisk::doDmaDataRead
void doDmaDataRead()
Definition: ide_disk.cc:378
IdeDisk::isBSYSet
bool isBSYSet()
Definition: ide_disk.hh:343
ide_atareg.h
IdeDisk::dmaWriteDone
void dmaWriteDone()
Definition: ide_disk.cc:549
ACT_CMD_COMPLETE
@ ACT_CMD_COMPLETE
Definition: ide_disk.hh:151
disk_image.hh
IdeDisk::updateState
void updateState(DevAction_t action)
Definition: ide_disk.cc:771
Transfer_Data_In
@ Transfer_Data_In
Definition: ide_disk.hh:181
IdeDisk::setController
void setController(IdeController *c, Addr page_bytes)
Set the controller for this device.
Definition: ide_disk.hh:286
PrdEntry
Definition: ide_disk.hh:69
Device_Idle_S
@ Device_Idle_S
Definition: ide_disk.hh:168
ACT_DATA_READ_BYTE
@ ACT_DATA_READ_BYTE
Definition: ide_disk.hh:156
IdeDisk::curPrd
PrdTableEntry curPrd
PRD entry.
Definition: ide_disk.hh:247
IdeDisk::dmaReadWaitEvent
EventFunctionWrapper dmaReadWaitEvent
Definition: ide_disk.hh:318
ACT_DATA_READY
@ ACT_DATA_READY
Definition: ide_disk.hh:155
Device_Srst
@ Device_Srst
Definition: ide_disk.hh:173
CommandReg::cyl_high
uint8_t cyl_high
Definition: ide_disk.hh:130
DevState
DevState
Definition: ide_disk.hh:166
IdeDisk::diskDelay
int diskDelay
The disk delay in microseconds.
Definition: ide_disk.hh:215
IdeDisk::dmaReadDone
void dmaReadDone()
Definition: ide_disk.cc:462
ACT_STAT_READ
@ ACT_STAT_READ
Definition: ide_disk.hh:154
IdeDisk::doDmaTransfer
void doDmaTransfer()
Definition: ide_disk.cc:333
IdeDisk::startDma
void startDma(const uint32_t &prdTableBase)
Definition: ide_disk.cc:592
Transfer_Data_Out
@ Transfer_Data_Out
Definition: ide_disk.hh:186
ACT_DATA_WRITE_BYTE
@ ACT_DATA_WRITE_BYTE
Definition: ide_disk.hh:158
PRD_COUNT_MASK
#define PRD_COUNT_MASK
Definition: ide_disk.hh:66
IdeDisk::abortDma
void abortDma()
Definition: ide_disk.cc:610
CommandReg::command
uint8_t command
Definition: ide_disk.hh:135
IdeDisk::pageBytes
Addr pageBytes
Size of OS pages.
Definition: ide_disk.hh:243
ACT_CMD_ERROR
@ ACT_CMD_ERROR
Definition: ide_disk.hh:152
Device_Dma_Abort
@ Device_Dma_Abort
Definition: ide_disk.hh:191
EventFunctionWrapper
Definition: eventq.hh:1101
Prepare_Data_Out
@ Prepare_Data_Out
Definition: ide_disk.hh:184
IdeDisk::dmaReadCG
ChunkGenerator * dmaReadCG
Definition: ide_disk.hh:317
IdeDisk::devState
DevState_t devState
Device state.
Definition: ide_disk.hh:237
MAX_SINGLE_DMA_SIZE
#define MAX_SINGLE_DMA_SIZE
Definition: ide_disk.hh:62
IdeDisk::writeDisk
void writeDisk(uint32_t sector, uint8_t *data)
Definition: ide_disk.cc:578
CommandReg::drive
uint8_t drive
Definition: ide_disk.hh:132
IdeDisk::dmaPrdReadDone
void dmaPrdReadDone()
Definition: ide_disk.cc:354
Stats::Scalar
This is a simple scalar statistic, like a counter.
Definition: statistics.hh:2533
Device_Idle_SI
@ Device_Idle_SI
Definition: ide_disk.hh:169
Events
Events
Definition: ide_disk.hh:138
PrdTableEntry::getEOT
uint16_t getEOT()
Definition: ide_disk.hh:90
IdeDisk::cmdBytes
uint32_t cmdBytes
Number of bytes in command data transfer.
Definition: ide_disk.hh:223
IdeDisk::cmdReg
CommandReg_t cmdReg
Command block registers.
Definition: ide_disk.hh:231
IdeDisk::dmaState
DmaState_t dmaState
Dma state.
Definition: ide_disk.hh:239
IdeDisk::readControl
void readControl(const Addr offset, int size, uint8_t *data)
Definition: ide_disk.cc:251
CommandReg_t
struct CommandReg CommandReg_t
cp
Definition: cprintf.cc:40
IdeDisk::dmaWriteEvent
EventFunctionWrapper dmaWriteEvent
Definition: ide_disk.hh:333
IdeDisk::regStats
void regStats() override
Register Statistics.
Definition: ide_disk.cc:390
None
@ None
Definition: ide_disk.hh:139
STATUS_BSY_BIT
#define STATUS_BSY_BIT
Definition: ide_disk.hh:114
DiskImage
Basic interface for accessing a disk image.
Definition: disk_image.hh:49
IdeDisk::isIENSet
bool isIENSet()
Definition: ide_disk.hh:344
PRD_BASE_MASK
#define PRD_BASE_MASK
Definition: ide_disk.hh:65
IdeDisk::doDmaDataWrite
void doDmaDataWrite()
Definition: ide_disk.cc:485
IdeDisk::intrClear
void intrClear()
Definition: ide_disk.cc:753
IdeDisk::pciToDma
Addr pciToDma(Addr pciAddr)
Definition: ide_disk.cc:192
IdeDisk::writeControl
void writeControl(const Addr offset, int size, const uint8_t *data)
Definition: ide_disk.cc:309
IdeDisk::dmaReadFullPages
Stats::Scalar dmaReadFullPages
Definition: ide_disk.hh:255
statistics.hh
Data_Ready_INTRQ_Out
@ Data_Ready_INTRQ_Out
Definition: ide_disk.hh:185
IdeDisk::startCommand
void startCommand()
Definition: ide_disk.cc:622
IdeDisk::curSector
uint32_t curSector
Current sector in access.
Definition: ide_disk.hh:229
CommandReg::sec_count
uint8_t sec_count
Definition: ide_disk.hh:127
IdeDisk::dmaWriteTxs
Stats::Scalar dmaWriteTxs
Definition: ide_disk.hh:260
PrdTableEntry::entry
PrdEntry_t entry
Definition: ide_disk.hh:77
ataparams
Definition: ide_atareg.h:67
ACT_NONE
@ ACT_NONE
Definition: ide_disk.hh:149
PrdEntry_t
struct PrdEntry PrdEntry_t
WriteWait
@ WriteWait
Definition: ide_disk.hh:142
STATUS_SEEK_BIT
#define STATUS_SEEK_BIT
Definition: ide_disk.hh:117
ACT_CMD_WRITE
@ ACT_CMD_WRITE
Definition: ide_disk.hh:150
IdeDisk::reset
void reset(int id)
Reset the device state.
Definition: ide_disk.cc:142
CommandReg
Definition: ide_disk.hh:124
ACT_DATA_READ_SHORT
@ ACT_DATA_READ_SHORT
Definition: ide_disk.hh:157
PrdEntry::baseAddr
uint32_t baseAddr
Definition: ide_disk.hh:70
IdeDisk::dmaAborted
bool dmaAborted
DMA Aborted.
Definition: ide_disk.hh:253
IdeDisk::dmaReadEvent
EventFunctionWrapper dmaReadEvent
Definition: ide_disk.hh:330
IdeDisk::dmaWriteFullPages
Stats::Scalar dmaWriteFullPages
Definition: ide_disk.hh:258
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
IdeDisk::setComplete
void setComplete()
Definition: ide_disk.hh:347
DevState_t
enum DevState DevState_t
IdeDisk::doDmaRead
void doDmaRead()
Definition: ide_disk.cc:423
PRD_EOT_MASK
#define PRD_EOT_MASK
Definition: ide_disk.hh:67
Transfer_Data_Dma
@ Transfer_Data_Dma
Definition: ide_disk.hh:190
IdeDisk
IDE Disk device model.
Definition: ide_disk.hh:205
PrdTableEntry
Definition: ide_disk.hh:75
IdeDisk::intrPending
bool intrPending
Interrupt pending.
Definition: ide_disk.hh:251
IdeDisk::driveID
struct ataparams driveID
Drive identification structure for this disk.
Definition: ide_disk.hh:219
PrdTableEntry::getByteCount
uint32_t getByteCount()
Definition: ide_disk.hh:84
Device_Idle_NS
@ Device_Idle_NS
Definition: ide_disk.hh:170
DmaRead
@ DmaRead
Definition: ide_disk.hh:144
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:197
IdeDisk::ctrl
IdeController * ctrl
The IDE controller for this disk.
Definition: ide_disk.hh:209
CommandReg::data
uint16_t data
Definition: ide_disk.hh:125
Command_Execution
@ Command_Execution
Definition: ide_disk.hh:176
IdeDisk::devID
int devID
Device ID (device0=0/device1=1)
Definition: ide_disk.hh:249
CommandReg::cyl_low
uint8_t cyl_low
Definition: ide_disk.hh:129
IdeDisk::image
DiskImage * image
The image that contains the data of this disk.
Definition: ide_disk.hh:211
ACT_SRST_CLEAR
@ ACT_SRST_CLEAR
Definition: ide_disk.hh:163
DevAction
DevAction
Definition: ide_disk.hh:148
Dma_Start
@ Dma_Start
Definition: ide_disk.hh:196
ReadWait
@ ReadWait
Definition: ide_disk.hh:141
PrdRead
@ PrdRead
Definition: ide_disk.hh:143
IdeDisk::readCommand
void readCommand(const Addr offset, int size, uint8_t *data)
Definition: ide_disk.cc:205
DevAction_t
enum DevAction DevAction_t
STATUS_DRDY_BIT
#define STATUS_DRDY_BIT
Definition: ide_disk.hh:115
ide_ctrl.hh
PrdEntry::byteCount
uint16_t byteCount
Definition: ide_disk.hh:71
IdeDisk::Params
IdeDiskParams Params
Definition: ide_disk.hh:263
CommandReg::sec_num
uint8_t sec_num
Definition: ide_disk.hh:128
DmaState_t
enum DmaState DmaState_t
IdeDisk::dmaRead
bool dmaRead
Dma transaction is a read.
Definition: ide_disk.hh:241
IdeDisk::isDEVSelect
bool isDEVSelect()
Definition: ide_disk.cc:186
CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:63
Data_Ready_INTRQ_In
@ Data_Ready_INTRQ_In
Definition: ide_disk.hh:180
ACT_DMA_DONE
@ ACT_DMA_DONE
Definition: ide_disk.hh:161
IdeDisk::IdeDisk
IdeDisk(const Params *p)
Definition: ide_disk.cc:61
ArmISA::c
Bitfield< 29 > c
Definition: miscregs_types.hh:50
IdeDisk::intrPost
void intrPost()
Definition: ide_disk.cc:738
IdeDisk::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: ide_disk.cc:1149
ChunkGenerator
This class takes an arbitrary memory region (address/length pair) and generates a series of appropria...
Definition: chunk_generator.hh:55
Dma_Transfer
@ Dma_Transfer
Definition: ide_disk.hh:197
Dma_Idle
@ Dma_Idle
Definition: ide_disk.hh:195
Prepare_Data_Dma
@ Prepare_Data_Dma
Definition: ide_disk.hh:189
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
IdeDisk::nIENBit
bool nIENBit
Interrupt enable bit.
Definition: ide_disk.hh:235
ACT_DATA_WRITE_SHORT
@ ACT_DATA_WRITE_SHORT
Definition: ide_disk.hh:159
CheckpointIn
Definition: serialize.hh:67
IdeDisk::cmdBytesLeft
uint32_t cmdBytesLeft
Number of bytes left in command data transfer.
Definition: ide_disk.hh:225
ACT_SELECT_WRITE
@ ACT_SELECT_WRITE
Definition: ide_disk.hh:153
IdeDisk::dmaReadTxs
Stats::Scalar dmaReadTxs
Definition: ide_disk.hh:257
IdeDisk::dataBuffer
uint8_t * dataBuffer
Data buffer for transfers.
Definition: ide_disk.hh:221
IdeDisk::writeCommand
void writeCommand(const Addr offset, int size, const uint8_t *data)
Definition: ide_disk.cc:261
ide_wdcreg.h
IdeDisk::drqBytesLeft
uint32_t drqBytesLeft
Number of bytes left in DRQ block.
Definition: ide_disk.hh:227
IdeDisk::dmaWriteBytes
Stats::Scalar dmaWriteBytes
Definition: ide_disk.hh:259
IdeDisk::doDmaWrite
void doDmaWrite()
Definition: ide_disk.cc:508
IdeDisk::dmaTransferEvent
EventFunctionWrapper dmaTransferEvent
Definition: ide_disk.hh:312
IdeDisk::dmaWriteCG
ChunkGenerator * dmaWriteCG
Definition: ide_disk.hh:323
IdeDisk::dmaWriteWaitEvent
EventFunctionWrapper dmaWriteWaitEvent
Definition: ide_disk.hh:324
IdeDisk::readDisk
void readDisk(uint32_t sector, uint8_t *data)
Definition: ide_disk.cc:568
ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:153
eventq.hh
SimObject
Abstract superclass for simulation objects.
Definition: sim_object.hh:92

Generated on Wed Sep 30 2020 14:02:11 for gem5 by doxygen 1.8.17