2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
30 static int cdrom_shmid
;
31 static void *cdrom_shmbuf
;
34 CDROM_SK_NOSENSE
= 0x0,
35 CDROM_SK_RECOVERED_ERROR
= 0x1,
36 CDROM_SK_NOT_READY
= 0x2,
37 CDROM_SK_MEDIUM_ERROR
= 0x3,
38 CDROM_SK_HARDWARE_ERROR
= 0x4,
39 CDROM_SK_ILLEGAL_REQUEST
= 0x5,
40 CDROM_SK_UNIT_ATTENTION
= 0x6,
41 CDROM_SK_DATA_PROTECT
= 0x7,
42 CDROM_SK_ABORTED_COMMAND
= 0xB,
43 CDROM_SK_MISCOMPARE
= 0xE
49 static int cdrom_command(struct cdrom_device
*dev
,cdrom_cmd_t
*cmd
,int dir
,size_t count
) {
50 if (count
>CDROM_BUFSIZE
) return -ERANGE
;
51 int sense_key
= rpc_call(dev
->rpc_func
,0,dev
->name
,cdrom_shmid
,count
,dir
,cmd
->raw32
[0],cmd
->raw32
[1],cmd
->raw32
[2],0,sizeof(cdrom_cmd_t
));
52 if (sense_key
==CDROM_SK_NOSENSE
) return 0;
55 struct cdrom_request_sense_data
*rqs
= cdrom_request_sense(dev
);
56 cdrom_error
.sense_key
= sense_key
;
57 cdrom_error
.asc
= rqs
->additional_sense_code
;
58 cdrom_error
.ascq
= rqs
->additional_sense_code_qualifier
;
63 struct cdrom_request_sense_data
*cdrom_request_sense(struct cdrom_device
*dev
) {
66 command
.dfl
.opcode
= CDROM_REQUEST_SENSE
;
67 command
.raw8
[4] = sizeof(struct cdrom_request_sense_data
);
68 if (cdrom_command(dev
,&command
,CDROM_R
,sizeof(struct cdrom_inquiry_data
))!=-1) {
69 fprintf(stderr
,"cdrom: %s request sense...\n",dev
->name
);
75 int cdrom_inquiry(struct cdrom_device
*dev
) {
77 struct cdrom_inquiry_data
*inq
= cdrom_shmbuf
;
79 command
.dfl
.opcode
= CDROM_INQUIRY
;
80 command
.raw8
[4] = sizeof(struct cdrom_inquiry_data
);
81 if (cdrom_command(dev
,&command
,CDROM_R
,sizeof(struct cdrom_inquiry_data
))!=-1) {
82 fprintf(stderr
,"cdrom: %s inquiry...\n",dev
->name
);
83 if (inq
->type
==5 && inq
->rmb
==1 && inq
->atapi_version
>=2 && inq
->response_type
==1) {
84 dev
->vendor_id
= bes(inq
->vendor_id
);
85 dev
->product_id
= bes(inq
->product_id
);
92 int cdrom_start(struct cdrom_device
*dev
,int start
,int load
) {
95 command
.dfl
.opcode
= CDROM_START_STOP
;
97 command
.raw8
[4] = (start
?1:0)|(load
?2:0);
98 if (cdrom_command(dev
,&command
,0,0)!=-1) {
99 fprintf(stderr
,"cdrom: %s start: start=%d; load=%d\n",dev
->name
,start
,load
);
100 dev
->started
= start
;
107 int cdrom_lock(struct cdrom_device
*dev
,int lock
) {
110 command
.dfl
.opcode
= CDROM_LOCK
;
111 command
.raw8
[4] = lock
?1:0;
112 if (cdrom_command(dev
,&command
,0,0)!=-1) {
113 fprintf(stderr
,"cdrom: %s lock: lock=%d\n",dev
->name
,lock
);
120 int cdrom_read_capacity(struct cdrom_device
*dev
) {
122 struct cdrom_read_capacity_data
*cap
= cdrom_shmbuf
;
124 command
.dfl
.opcode
= CDROM_READ_CAPACITY
;
125 if (cdrom_command(dev
,&command
,CDROM_R
,sizeof(struct cdrom_read_capacity_data
))!=-1) {
126 dev
->block_count
= bei(cap
->lba
);
127 dev
->block_size
= bei(cap
->block_size
);
128 fprintf(stderr
,"cdrom: %s read_capacity: lba=0x%x; block_size=0x%x; size=%dkB\n",dev
->name
,dev
->block_count
,dev
->block_size
,(dev
->block_count
*dev
->block_size
)/1024);
134 void *cdrom_read(struct cdrom_device
*dev
,size_t first_block
,size_t block_count
) {
135 fprintf(stderr
,"cdrom: %s read: first_block=0x%x block_count=0x%x\n",dev
->name
,first_block
,block_count
);
138 command
.ext
.opcode
= CDROM_READ
;
139 command
.ext
.lba
= bei(first_block
);
140 command
.ext
.length
= bei(block_count
);
141 return cdrom_command(dev
,&command
,CDROM_R
,block_count
*dev
->block_size
)!=-1?cdrom_shmbuf
:NULL
;
144 struct cdrom_device
*cdrom_device_create(const char *name
) {
145 struct cdrom_device
*dev
= malloc(sizeof(struct cdrom_device
));
146 memset(dev
,0,sizeof(struct cdrom_device
));
148 dev
->name
= strdup(name
);
149 asprintf(&(dev
->rpc_func
),"scsi_request_%s",name
);
154 void cdrom_device_destroy(struct cdrom_device
*dev
) {
159 int cdrom_buf_init() {
160 cdrom_shmid
= shmget(IPC_PRIVATE
,CDROM_BUFSIZE
,0);
161 if (cdrom_shmid
!=-1) {
162 cdrom_shmbuf
= shmat(cdrom_shmid
,NULL
,0);
163 if (cdrom_shmbuf
!=NULL
) return 0;
164 else shmctl(cdrom_shmid
,IPC_RMID
,NULL
);
166 memset(&cdrom_error
,0,sizeof(cdrom_error
));