📄 floppy.c.txt
字号:
1045 }
1046 sector = block % floppy->sect;
1047 block /= floppy->sect;
1048 head = block % floppy->head;
1049 track = block / floppy->head;
1050 seek_track = track << floppy->stretch;
1051 if (CURRENT->cmd == READ)
1052 command = FD_READ;
1053 else if (CURRENT->cmd == WRITE)
1054 command = FD_WRITE;
1055 else {
1056 printk("do_fd_request: unknown command\n");
1057 request_done(0);
1058 goto repeat;
1059 }
1060 } else {
1061 if (current_drive != (format_req.device & 3))
1062 current_track = NO_TRACK;
1063 current_drive = format_req.device & 3;
1064 if (((unsigned) format_req.track) >= floppy->track ||
1065 (format_req.head & 0xfffe) || probing) {
1066 request_done(0);
1067 goto repeat;
1068 }
1069 head = format_req.head;
1070 track = format_req.track;
1071 seek_track = track << floppy->stretch;
1072 if (seek_track == buffer_track) buffer_track = -1;
1073 command = FD_FORMAT;
1074 setup_format_params();
1075 }
1076 timer_table[FLOPPY_TIMER].expires = jiffies+10*HZ;
1077 timer_active |= 1 << FLOPPY_TIMER;
1078 if ((seek_track == buffer_track) &&
1079 (current_drive == buffer_drive)) {
1080 buffer_area = floppy_track_buffer +
1081 ((sector + head*floppy->sect)<<9);
1082 if (command == FD_READ) {
1083 copy_buffer(buffer_area,CURRENT->buffer);
1084 request_done(1);
1085 goto repeat;
1086 } else if (command == FD_WRITE)
1087 copy_buffer(CURRENT->buffer,buffer_area);
1088 }
1089 if (seek_track != current_track)
1090 seek = 1;
1091 sector++;
1092 del_timer(motor_off_timer + current_drive);
1093 floppy_on(current_drive);
1094 }
1095
1096 void do_fd_request(void)
1097 {
1098 cli();
1099 while (fdc_busy) sleep_on(&fdc_wait);
1100 fdc_busy = 1;
1101 sti();
1102 redo_fd_request();
1103 }
1104
1105 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1106 unsigned long param)
1107 {
1108 int i,drive,cnt,okay;
1109 struct floppy_struct *this_floppy;
1110
1111 switch (cmd) {
1112 RO_IOCTLS(inode->i_rdev,param);
1113 }
1114 drive = MINOR(inode->i_rdev);
1115 switch (cmd) {
1116 case FDFMTBEG:
1117 if (!suser())
1118 return -EPERM;
1119 return 0;
1120 case FDFMTEND:
1121 if (!suser())
1122 return -EPERM;
1123 cli();
1124 fake_change |= 1 << (drive & 3);
1125 sti();
1126 drive &= 3;
1127 cmd = FDCLRPRM;
1128 break;
1129 case FDGETPRM:
1130 if (drive > 3) this_floppy = &floppy_type[drive >> 2];
1131 else if ((this_floppy = current_type[drive & 3]) == NULL)
1132 return -ENODEV;
1133 i = verify_area(VERIFY_WRITE,(void *) param,sizeof(struct floppy_struct));
1134 if (i)
1135 return i;
1136 for (cnt = 0; cnt < sizeof(struct floppy_struct); cnt++)
1137 put_fs_byte(((char *) this_floppy)[cnt],
1138 (char *) param+cnt);
1139 return 0;
1140 case FDFMTTRK:
1141 if (!suser())
1142 return -EPERM;
1143 if (fd_ref[drive & 3] != 1)
1144 return -EBUSY;
1145 cli();
1146 while (format_status != FORMAT_NONE)
1147 sleep_on(&format_done);
1148 for (cnt = 0; cnt < sizeof(struct format_descr); cnt++)
1149 ((char *) &format_req)[cnt] = get_fs_byte(
1150 (char *) param+cnt);
1151 format_req.device = drive;
1152 format_status = FORMAT_WAIT;
1153 format_errors = 0;
1154 while (format_status != FORMAT_OKAY && format_status !=
1155 FORMAT_ERROR) {
1156 if (fdc_busy) sleep_on(&fdc_wait);
1157 else {
1158 fdc_busy = 1;
1159 redo_fd_request();
1160 }
1161 }
1162 while (format_status != FORMAT_OKAY && format_status !=
1163 FORMAT_ERROR)
1164 sleep_on(&format_done);
1165 sti();
1166 okay = format_status == FORMAT_OKAY;
1167 format_status = FORMAT_NONE;
1168 floppy_off(drive & 3);
1169 wake_up(&format_done);
1170 return okay ? 0 : -EIO;
1171 case FDFLUSH:
1172 if (!permission(inode, 2))
1173 return -EPERM;
1174 cli();
1175 fake_change |= 1 << (drive & 3);
1176 sti();
1177 check_disk_change(inode->i_rdev);
1178 return 0;
1179 }
1180 if (!suser())
1181 return -EPERM;
1182 if (drive < 0 || drive > 3)
1183 return -EINVAL;
1184 switch (cmd) {
1185 case FDCLRPRM:
1186 current_type[drive] = NULL;
1187 floppy_sizes[drive] = MAX_DISK_SIZE;
1188 keep_data[drive] = 0;
1189 break;
1190 case FDSETPRM:
1191 case FDDEFPRM:
1192 memcpy_fromfs(user_params+drive,
1193 (void *) param,
1194 sizeof(struct floppy_struct));
1195 current_type[drive] = &user_params[drive];
1196 floppy_sizes[drive] = user_params[drive].size >> 1;
1197 if (cmd == FDDEFPRM)
1198 keep_data[drive] = -1;
1199 else {
1200 cli();
1201 while (fdc_busy) sleep_on(&fdc_wait);
1202 fdc_busy = 1;
1203 sti();
1204 outb_p((current_DOR & 0xfc) | drive |
1205 (0x10 << drive),FD_DOR);
1206 for (cnt = 0; cnt < 1000; cnt++) __asm__("nop");
1207 if (inb(FD_DIR) & 0x80)
1208 keep_data[drive] = 1;
1209 else
1210 keep_data[drive] = 0;
1211 outb_p(current_DOR,FD_DOR);
1212 fdc_busy = 0;
1213 wake_up(&fdc_wait);
1214 }
1215 break;
1216 case FDMSGON:
1217 ftd_msg[drive] = 1;
1218 break;
1219 case FDMSGOFF:
1220 ftd_msg[drive] = 0;
1221 break;
1222 case FDSETEMSGTRESH:
1223 min_report_error_cnt[drive] = (unsigned short) (param & 0x0f);
1224 break;
1225 default:
1226 return -EINVAL;
1227 }
1228 return 0;
1229 }
1230
1231 #define CMOS_READ(addr) ({ \
1232 outb_p(addr,0x70); \
1233 inb_p(0x71); \
1234 })
1235
1236 static struct floppy_struct *find_base(int drive,int code)
1237 {
1238 struct floppy_struct *base;
1239
1240 if (code > 0 && code < 5) {
1241 base = &floppy_types[(code-1)*2];
1242 printk("fd%d is %s",drive,base->name);
1243 return base;
1244 }
1245 printk("fd%d is unknown type %d",drive,code);
1246 return NULL;
1247 }
1248
1249 static void config_types(void)
1250 {
1251 printk("Floppy drive(s): ");
1252 base_type[0] = find_base(0,(CMOS_READ(0x10) >> 4) & 15);
1253 if (((CMOS_READ(0x14) >> 6) & 1) == 0)
1254 base_type[1] = NULL;
1255 else {
1256 printk(", ");
1257 base_type[1] = find_base(1,CMOS_READ(0x10) & 15);
1258 }
1259 base_type[2] = base_type[3] = NULL;
1260 printk("\n");
1261 }
1262
1263 /*
1264 * floppy_open check for aliasing (/dev/fd0 can be the same as
1265 * /dev/PS0 etc), and disallows simultaneous access to the same
1266 * drive with different device numbers.
1267 */
1268 static int floppy_open(struct inode * inode, struct file * filp)
1269 {
1270 int drive;
1271 int old_dev;
1272
1273 drive = inode->i_rdev & 3;
1274 old_dev = fd_device[drive];
1275 if (fd_ref[drive])
1276 if (old_dev != inode->i_rdev)
1277 return -EBUSY;
1278 fd_ref[drive]++;
1279 fd_device[drive] = inode->i_rdev;
1280 buffer_drive = buffer_track = -1;
1281 if (old_dev && old_dev != inode->i_rdev)
1282 invalidate_buffers(old_dev);
1283 if (filp && filp->f_mode)
1284 check_disk_change(inode->i_rdev);
1285 return 0;
1286 }
1287
1288 static void floppy_release(struct inode * inode, struct file * filp)
1289 {
1290 sync_dev(inode->i_rdev);
1291 if (!fd_ref[inode->i_rdev & 3]--) {
1292 printk("floppy_release with fd_ref == 0");
1293 fd_ref[inode->i_rdev & 3] = 0;
1294 }
1295 }
1296
1297 static struct file_operations floppy_fops = {
1298 NULL, /* lseek - default */
1299 block_read, /* read - general block-dev read */
1300 block_write, /* write - general block-dev write */
1301 NULL, /* readdir - bad */
1302 NULL, /* select */
1303 fd_ioctl, /* ioctl */
1304 NULL, /* mmap */
1305 floppy_open, /* open */
1306 floppy_release, /* release */
1307 block_fsync /* fsync */
1308 };
1309
1310
1311 /*
1312 * The version command is not supposed to generate an interrupt, but
1313 * my FDC does, except when booting in SVGA screen mode.
1314 * When it does generate an interrupt, it doesn't return any status bytes.
1315 * It appears to have something to do with the version command...
1316 *
1317 * This should never be called, because of the reset after the version check.
1318 */
1319 static void ignore_interrupt(void)
1320 {
1321 printk(DEVICE_NAME ": weird interrupt ignored (%d)\n", result());
1322 reset = 1;
1323 CLEAR_INTR; /* ignore only once */
1324 }
1325
1326
1327 static void floppy_interrupt(int unused)
1328 {
1329 void (*handler)(void) = DEVICE_INTR;
1330
1331 DEVICE_INTR = NULL;
1332 if (!handler)
1333 handler = unexpected_floppy_interrupt;
1334 handler();
1335 }
1336
1337 /*
1338 * This is the floppy IRQ description. The SA_INTERRUPT in sa_flags
1339 * means we run the IRQ-handler with interrupts disabled.
1340 */
1341 static struct sigaction floppy_sigaction = {
1342 floppy_interrupt,
1343 0,
1344 SA_INTERRUPT,
1345 NULL
1346 };
1347
1348 void floppy_init(void)
1349 {
1350 outb(current_DOR,FD_DOR);
1351 if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
1352 printk("Unable to get major %d for floppy\n",MAJOR_NR);
1353 return;
1354 }
1355 blk_size[MAJOR_NR] = floppy_sizes;
1356 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1357 timer_table[FLOPPY_TIMER].fn = floppy_shutdown;
1358 timer_active &= ~(1 << FLOPPY_TIMER);
1359 config_types();
1360 if (irqaction(FLOPPY_IRQ,&floppy_sigaction))
1361 printk("Unable to grab IRQ%d for the floppy driver\n", FLOPPY_IRQ);
1362 if (request_dma(FLOPPY_DMA))
1363 printk("Unable to grab DMA%d for the floppy driver\n", FLOPPY_DMA);
1364 /* Try to determine the floppy controller type */
1365 DEVICE_INTR = ignore_interrupt; /* don't ask ... */
1366 output_byte(FD_VERSION); /* get FDC version code */
1367 if (result() != 1) {
1368 printk(DEVICE_NAME ": FDC failed to return version byte\n");
1369 fdc_version = FDC_TYPE_STD;
1370 } else
1371 fdc_version = reply_buffer[0];
1372 if (fdc_version != FDC_TYPE_STD)
1373 printk(DEVICE_NAME ": FDC version 0x%x\n", fdc_version);
1374 #ifndef FDC_FIFO_UNTESTED
1375 fdc_version = FDC_TYPE_STD; /* force std fdc type; can't test other. */
1376 #endif
1377
1378 /* Not all FDCs seem to be able to handle the version command
1379 * properly, so force a reset for the standard FDC clones,
1380 * to avoid interrupt garbage.
1381 */
1382
1383 if (fdc_version == FDC_TYPE_STD) {
1384 initial_reset_flag = 1;
1385 reset_floppy();
1386 }
1387 }
1388
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -