1 /*
2  * Copyright (c) 2023, Google Inc. All rights reserved.
3  * Author: codycswong@google.com (Cody Wong)
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files
7  * (the "Software"), to deal in the Software without restriction,
8  * including without limitation the rights to use, copy, modify, merge,
9  * publish, distribute, sublicense, and/or sell copies of the Software,
10  * and to permit persons to whom the Software is furnished to do so,
11  * subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #pragma once
25 
26 #include <dev/virtio/9p.h>
27 #include <kernel/event.h>
28 #include <kernel/mutex.h>
29 #include <lk/list.h>
30 #include <sys/types.h>
31 #include <string.h>
32 
33 #define VIRTIO_9P_RPC_TIMEOUT 3000 /* ms */
34 #define VIRTIO_9P_DEFAULT_MSIZE (PAGE_SIZE << 5)
35 
36 struct p9_fcall {
37     uint32_t size;
38 
39     size_t offset;
40     size_t capacity;
41 
42     uint8_t *sdata;
43 };
44 
45 struct p9_req {
46     int status;
47     event_t io_event;
48     struct p9_fcall tc;
49     struct p9_fcall rc;
50 };
51 
52 enum {
53     P9_REQ_S_UNKNOWN = 0,
54     P9_REQ_S_INITIALIZED,
55     P9_REQ_S_SENT,
56     P9_REQ_S_RECEIVED,
57 };
58 
59 struct virtio_9p_dev {
60     struct virtio_device *dev;
61     struct virtio_9p_config *config;
62     bdev_t bdev;
63 
64     uint32_t msize;
65     struct p9_req req;
66     mutex_t req_lock;
67 
68     struct list_node list;
69     spin_lock_t lock;
70 };
71 
72 // read/write APIs of basic types
73 size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size);
74 size_t pdu_write(struct p9_fcall *pdu, void *data, size_t size);
75 status_t pdu_writeb(struct p9_fcall *pdu, uint8_t byte);
76 uint8_t pdu_readb(struct p9_fcall *pdu);
77 status_t pdu_writew(struct p9_fcall *pdu, uint16_t word);
78 uint16_t pdu_readw(struct p9_fcall *pdu);
79 status_t pdu_writed(struct p9_fcall *pdu, uint32_t dword);
80 uint32_t pdu_readd(struct p9_fcall *pdu);
81 status_t pdu_writeq(struct p9_fcall *pdu, uint64_t qword);
82 uint64_t pdu_readq(struct p9_fcall *pdu);
83 status_t pdu_writestr(struct p9_fcall *pdu, const char *str);
84 char *pdu_readstr(struct p9_fcall *pdu);
85 virtio_9p_qid_t pdu_readqid(struct p9_fcall *pdu);
86 status_t pdu_writedata(struct p9_fcall *pdu, const uint8_t *data, uint32_t count);
87 uint8_t *pdu_readdata(struct p9_fcall *pdu, uint32_t *count);
88 
89 // Plan 9 File Protocol APIs
90 status_t p9_proto_tversion(struct p9_req *req, const virtio_9p_msg_t *tmsg);
91 status_t p9_proto_rversion(struct p9_req *req, virtio_9p_msg_t *rmsg);
92 status_t p9_proto_tattach(struct p9_req *req, const virtio_9p_msg_t *tmsg);
93 status_t p9_proto_rattach(struct p9_req *req, virtio_9p_msg_t *rmsg);
94 status_t p9_proto_twalk(struct p9_req *req, const virtio_9p_msg_t *tmsg);
95 status_t p9_proto_rwalk(struct p9_req *req, virtio_9p_msg_t *rmsg);
96 status_t p9_proto_topen(struct p9_req *req, const virtio_9p_msg_t *tmsg);
97 status_t p9_proto_ropen(struct p9_req *req, virtio_9p_msg_t *rmsg);
98 status_t p9_proto_tlopen(struct p9_req *req, const virtio_9p_msg_t *tmsg);
99 status_t p9_proto_rlopen(struct p9_req *req, virtio_9p_msg_t *rmsg);
100 status_t p9_proto_tgetattr(struct p9_req *req, const virtio_9p_msg_t *tmsg);
101 status_t p9_proto_rgetattr(struct p9_req *req, virtio_9p_msg_t *rmsg);
102 status_t p9_proto_tread(struct p9_req *req, const virtio_9p_msg_t *tmsg);
103 status_t p9_proto_rread(struct p9_req *req, virtio_9p_msg_t *rmsg);
104 status_t p9_proto_twrite(struct p9_req *req, const virtio_9p_msg_t *tmsg);
105 status_t p9_proto_rwrite(struct p9_req *req, virtio_9p_msg_t *rmsg);
106 status_t p9_proto_tclunk(struct p9_req *req, const virtio_9p_msg_t *tmsg);
107 status_t p9_proto_rclunk(struct p9_req *req, virtio_9p_msg_t *rmsg);
108 status_t p9_proto_tremove(struct p9_req *req, const virtio_9p_msg_t *tmsg);
109 status_t p9_proto_rremove(struct p9_req *req, virtio_9p_msg_t *rmsg);
110 status_t p9_proto_rlerror(struct p9_req *req, virtio_9p_msg_t *rmsg);
111 status_t p9_proto_tlcreate(struct p9_req *req, const virtio_9p_msg_t *tmsg);
112 status_t p9_proto_rlcreate(struct p9_req *req, virtio_9p_msg_t *rmsg);
113 status_t p9_proto_treaddir(struct p9_req *req, const virtio_9p_msg_t *tmsg);
114 status_t p9_proto_rreaddir(struct p9_req *req, virtio_9p_msg_t *rmsg);
115 status_t p9_proto_tmkdir(struct p9_req *req, const virtio_9p_msg_t *tmsg);
116 status_t p9_proto_rmkdir(struct p9_req *req, virtio_9p_msg_t *rmsg);
117