Corrected debug message
[meinos.git] / apps / cdrom / device.c
blob97fd1233f052b97acdbb9e870a0638121102bcad
1 /*
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>
20 #include <sys/shm.h>
21 #include <stdlib.h>
22 #include <stdint.h>
23 #include <limits.h>
24 #include <stdio.h>
25 #include <rpc.h>
26 #include <unistd.h>
28 #include "device.h"
30 static int cdrom_shmid;
31 static void *cdrom_shmbuf;
32 struct {
33 enum {
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
44 } sense_key;
45 unsigned int asc;
46 unsigned int ascq;
47 } cdrom_error;
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;
53 else {
54 // p55, p183, p179
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;
59 return -1;
63 struct cdrom_request_sense_data *cdrom_request_sense(struct cdrom_device *dev) {
64 cdrom_cmd_t command;
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);
70 return cdrom_shmbuf;
72 else return NULL;
75 int cdrom_inquiry(struct cdrom_device *dev) {
76 cdrom_cmd_t command;
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);
86 return 0;
89 return -1;
92 int cdrom_start(struct cdrom_device *dev,int start,int load) {
93 cdrom_cmd_t command;
95 command.dfl.opcode = CDROM_START_STOP;
96 command.raw8[1] = 0;
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;
101 dev->loaded = load;
102 return 0;
104 else return -1;
107 int cdrom_lock(struct cdrom_device *dev,int lock) {
108 cdrom_cmd_t command;
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);
114 dev->locked = lock;
115 return 0;
117 else return -1;
120 int cdrom_read_capacity(struct cdrom_device *dev) {
121 cdrom_cmd_t command;
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);
129 return 0;
131 else return -1;
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);
136 cdrom_cmd_t command;
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);
151 return dev;
154 void cdrom_device_destroy(struct cdrom_device *dev) {
155 free(dev->name);
156 free(dev->rpc_func);
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));
167 return -1;