1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#define DBG_TAG "scsi.blk"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
struct scsi_cdrom
{
struct rt_blk_disk parent;
struct rt_scsi_device *sdev;
int cdrom_id;
struct rt_device_blk_geometry geometry;
};
#define raw_to_scsi_cdrom(raw) rt_container_of(raw, struct scsi_cdrom, parent)
static struct rt_dm_ida cdrom_ida = RT_DM_IDA_INIT(CUSTOM);
static struct rt_dm_ida scsi_cdrom_ida = RT_DM_IDA_INIT(SCSI_CDROM);
static rt_ssize_t scsi_cdrom_read(struct rt_blk_disk *disk, rt_off_t sector,
void *buffer, rt_size_t sector_count)
{
rt_err_t err;
struct scsi_cdrom *scdrom = raw_to_scsi_cdrom(disk);
struct rt_scsi_device *sdev = scdrom->sdev;
sector_count &= RT_UINT32_MAX;
if (sector >> 32)
{
err = rt_scsi_read16(sdev, sector, buffer, sector_count);
}
else
{
err = rt_scsi_read12(sdev, sector, buffer, sector_count);
}
return !err ? sector_count : (rt_ssize_t)err;
}
static rt_err_t scsi_cdrom_getgeome(struct rt_blk_disk *disk,
struct rt_device_blk_geometry *geometry)
{
struct scsi_cdrom *scdrom = raw_to_scsi_cdrom(disk);
rt_memcpy(geometry, &scdrom->geometry, sizeof(scdrom->geometry));
return RT_EOK;
}
static const struct rt_blk_disk_ops scsi_cdrom_ops =
{
.read = scsi_cdrom_read,
.getgeome = scsi_cdrom_getgeome,
};
rt_err_t scsi_cdrom_probe(struct rt_scsi_device *sdev)
{
rt_err_t err;
union
{
struct rt_scsi_read_capacity10_data capacity10;
struct rt_scsi_read_capacity16_data capacity16;
} data;
struct scsi_cdrom *scdrom = rt_calloc(1, sizeof(*scdrom));
if (!scdrom)
{
return -RT_ENOMEM;
}
if ((scdrom->cdrom_id = rt_dm_ida_alloc(&cdrom_ida)) < 0)
{
return -RT_EFULL;
}
sdev->priv = scdrom;
scdrom->sdev = sdev;
scdrom->parent.ida = &scsi_cdrom_ida;
scdrom->parent.read_only = RT_TRUE;
scdrom->parent.parallel_io = RT_FALSE;
scdrom->parent.ops = &scsi_cdrom_ops;
scdrom->parent.max_partitions = RT_BLK_PARTITION_NONE;
if ((err = rt_scsi_read_capacity10(sdev, &data.capacity10)))
{
goto _fail;
}
if (data.capacity10.last_block == 0xffffffff)
{
if ((err = rt_scsi_read_capacity16(sdev, &data.capacity16)))
{
goto _fail;
}
}
scdrom->geometry.bytes_per_sector = sdev->block_size;
scdrom->geometry.block_size = sdev->block_size;
scdrom->geometry.sector_count = sdev->last_block + 1;
rt_dm_dev_set_name(&scdrom->parent.parent, "cdrom%u", scdrom->cdrom_id);
if ((err = rt_hw_blk_disk_register(&scdrom->parent)))
{
goto _fail;
}
return RT_EOK;
_fail:
rt_dm_ida_free(&cdrom_ida, scdrom->cdrom_id);
rt_free(scdrom);
return err;
}
rt_err_t scsi_cdrom_remove(struct rt_scsi_device *sdev)
{
struct scsi_cdrom *scdrom = sdev->priv;
rt_dm_ida_free(&cdrom_ida, scdrom->cdrom_id);
return rt_hw_blk_disk_unregister(&scdrom->parent);
}
|