1*e73bd0a1SAndrew Jeffery #pragma once
2*e73bd0a1SAndrew Jeffery 
3*e73bd0a1SAndrew Jeffery #include "NVMeContext.hpp"
4*e73bd0a1SAndrew Jeffery 
5*e73bd0a1SAndrew Jeffery #include <boost/asio/io_service.hpp>
6*e73bd0a1SAndrew Jeffery #include <boost/asio/posix/stream_descriptor.hpp>
7*e73bd0a1SAndrew Jeffery 
8*e73bd0a1SAndrew Jeffery #include <thread>
9*e73bd0a1SAndrew Jeffery 
10*e73bd0a1SAndrew Jeffery class NVMeBasicContext : public NVMeContext
11*e73bd0a1SAndrew Jeffery {
12*e73bd0a1SAndrew Jeffery   public:
13*e73bd0a1SAndrew Jeffery     NVMeBasicContext(boost::asio::io_service& io, int rootBus);
14*e73bd0a1SAndrew Jeffery     ~NVMeBasicContext() override = default;
15*e73bd0a1SAndrew Jeffery     void pollNVMeDevices() override;
16*e73bd0a1SAndrew Jeffery     void readAndProcessNVMeSensor() override;
17*e73bd0a1SAndrew Jeffery     void processResponse(std::shared_ptr<NVMeSensor>& sensor, void* msg,
18*e73bd0a1SAndrew Jeffery                          size_t len) override;
19*e73bd0a1SAndrew Jeffery 
20*e73bd0a1SAndrew Jeffery   private:
21*e73bd0a1SAndrew Jeffery     NVMeBasicContext(boost::asio::io_service& io, int rootBus, int cmdOut,
22*e73bd0a1SAndrew Jeffery                      int streamIn, int streamOut, int cmdIn);
23*e73bd0a1SAndrew Jeffery     boost::asio::io_service& io;
24*e73bd0a1SAndrew Jeffery 
25*e73bd0a1SAndrew Jeffery     // The IO thread must be destructed after the stream descriptors, so
26*e73bd0a1SAndrew Jeffery     // initialise it first. http://eel.is/c++draft/class.base.init#note-6
27*e73bd0a1SAndrew Jeffery     //
28*e73bd0a1SAndrew Jeffery     // Providing a stop-source to the thread execution function isn't
29*e73bd0a1SAndrew Jeffery     // particularly useful as it will spend most of its time blocked in a system
30*e73bd0a1SAndrew Jeffery     // call - ioctl() for the actual device communication, or read() and write()
31*e73bd0a1SAndrew Jeffery     // on the pipes associated with reqStream and respStream. Rather than trying
32*e73bd0a1SAndrew Jeffery     // to force a stop, rely on read()/write() failures from closed pipes to
33*e73bd0a1SAndrew Jeffery     // coerce it to exit and thus allow completion of the join().
34*e73bd0a1SAndrew Jeffery     std::jthread thread;
35*e73bd0a1SAndrew Jeffery 
36*e73bd0a1SAndrew Jeffery     // Destruction of the stream descriptors has the effect of issuing cancel(),
37*e73bd0a1SAndrew Jeffery     // destroying the closure of the callback where we might be carrying
38*e73bd0a1SAndrew Jeffery     // weak_ptrs to `this`.
39*e73bd0a1SAndrew Jeffery     // https://www.boost.org/doc/libs/1_79_0/doc/html/boost_asio/reference/posix__basic_descriptor/_basic_descriptor.html
40*e73bd0a1SAndrew Jeffery     boost::asio::posix::stream_descriptor reqStream;
41*e73bd0a1SAndrew Jeffery     boost::asio::posix::stream_descriptor respStream;
42*e73bd0a1SAndrew Jeffery 
43*e73bd0a1SAndrew Jeffery     enum
44*e73bd0a1SAndrew Jeffery     {
45*e73bd0a1SAndrew Jeffery         NVME_MI_BASIC_SFLGS_DRIVE_NOT_READY = 0x40,
46*e73bd0a1SAndrew Jeffery         NVME_MI_BASIC_SFLGS_DRIVE_FUNCTIONAL = 0x20,
47*e73bd0a1SAndrew Jeffery     };
48*e73bd0a1SAndrew Jeffery };
49