dasd.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:131k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1.       fdata->start_unit, rc);
  2. break;
  3. dasd_free_request (req, device); /* request is no longer used */
  4.         if ( signal_pending(current) ) {
  5. rc = -ERESTARTSYS;
  6. break;
  7.                 }
  8. fdata->start_unit++;
  9. }
  10. return rc;
  11. } /* end dasd_format */
  12. static struct list_head dasd_ioctls = LIST_HEAD_INIT (dasd_ioctls);
  13. static dasd_ioctl_list_t *
  14. dasd_find_ioctl (int no)
  15. {
  16. struct list_head *curr;
  17. list_for_each (curr, &dasd_ioctls) {
  18. if (list_entry (curr, dasd_ioctl_list_t, list)->no == no) {
  19. return list_entry (curr, dasd_ioctl_list_t, list);
  20. }
  21. }
  22. return NULL;
  23. }
  24. int
  25. dasd_ioctl_no_register (struct module *owner, int no, dasd_ioctl_fn_t handler)
  26. {
  27. dasd_ioctl_list_t *new;
  28. if (dasd_find_ioctl (no))
  29. return -EBUSY;
  30. new = kmalloc (sizeof (dasd_ioctl_list_t), GFP_KERNEL);
  31. if (new == NULL)
  32. return -ENOMEM;
  33. new->owner = owner;
  34. new->no = no;
  35. new->handler = handler;
  36. list_add (&new->list, &dasd_ioctls);
  37. MOD_INC_USE_COUNT;
  38. return 0;
  39. }
  40. int
  41. dasd_ioctl_no_unregister (struct module *owner, int no, dasd_ioctl_fn_t handler)
  42. {
  43. dasd_ioctl_list_t *old = dasd_find_ioctl (no);
  44. if (old == NULL)
  45. return -ENOENT;
  46. if (old->no != no || old->handler != handler || owner != old->owner )
  47. return -EINVAL;
  48. list_del (&old->list);
  49. kfree (old);
  50. MOD_DEC_USE_COUNT;
  51. return 0;
  52. }
  53. static int
  54. dasd_revalidate (dasd_device_t * device)
  55. {
  56.         int rc = 0;
  57. int i;
  58. kdev_t kdev = device->kdev;
  59. int openct = atomic_read (&device->open_count);
  60. int start = MINOR (kdev);
  61. if (openct != 1) {
  62. DASD_MESSAGE (KERN_WARNING, device, "%s",
  63.       "BLKRRPART: device is open! expect errors.");
  64. }
  65. for (i = (1 << DASD_PARTN_BITS) - 1; i >= 0; i--) {
  66.                 int major = device->major_info->gendisk.major;
  67. invalidate_device(MKDEV (major, start+i), 1);
  68. }
  69.         dasd_destroy_partitions(device);
  70.         dasd_setup_partitions(device);
  71.         return rc;
  72. }
  73. static int
  74. do_dasd_ioctl (struct inode *inp, /* unsigned */ int no, unsigned long data)
  75. {
  76. int rc = 0;
  77. dasd_device_t *device = dasd_device_from_kdev (inp->i_rdev);
  78. major_info_t *major_info;
  79. if (!device) {
  80. printk (KERN_WARNING PRINTK_HEADER
  81. "No device registered as device (%d:%d)n",
  82. MAJOR (inp->i_rdev), 
  83.                         MINOR (inp->i_rdev));
  84. return -EINVAL;
  85. }
  86. if ((_IOC_DIR (no) != _IOC_NONE) && (data == 0)) {
  87. PRINT_DEBUG ("empty data ptr");
  88. return -EINVAL;
  89. }
  90. major_info = device->major_info;
  91. #if 0
  92. printk (KERN_DEBUG PRINTK_HEADER
  93. "ioctl 0x%08x %s'0x%x'%d(%d) on /dev/%s (%d:%d,"
  94. " devno 0x%04x on irq %d) with data %8lxn",
  95. no,
  96. _IOC_DIR (no) == _IOC_NONE ? "0" :
  97. _IOC_DIR (no) == _IOC_READ ? "r" :
  98. _IOC_DIR (no) == _IOC_WRITE ? "w" :
  99. _IOC_DIR (no) == (_IOC_READ | _IOC_WRITE) ? "rw" : "u",
  100. _IOC_TYPE (no),
  101.                 _IOC_NR (no),
  102.                 _IOC_SIZE (no),
  103. device->name, 
  104.                 MAJOR (inp->i_rdev), 
  105.                 MINOR (inp->i_rdev),
  106. device->devinfo.devno, 
  107.                 device->devinfo.irq, 
  108.                 data);
  109. #endif
  110. switch (no) {
  111.         case DASDAPIVER: {
  112. int ver = DASD_API_VERSION;
  113. rc = put_user(ver, (int *) data);
  114. break;
  115.         }
  116. case BLKGETSIZE:{ /* Return device size */
  117. long blocks = major_info->gendisk.sizes 
  118.                                       [MINOR (inp->i_rdev)] << 1;
  119. rc = put_user(blocks, (long *) data);
  120. break;
  121. }
  122. case BLKGETSIZE64:{
  123. u64 blocks = major_info->gendisk.sizes 
  124.                                       [MINOR (inp->i_rdev)];
  125. rc = put_user(blocks << 10, (u64 *) data);
  126. break;
  127. }
  128. case BLKRRPART:{
  129. if (!capable (CAP_SYS_ADMIN)) {
  130. rc = -EACCES;
  131. break;
  132. }
  133. rc = dasd_revalidate (device);
  134. break;
  135. }
  136. case HDIO_GETGEO:{
  137. struct hd_geometry geo = { 0, };
  138. rc = dasd_fillgeo (inp->i_rdev, &geo);
  139. if (rc)
  140. break;
  141. rc = copy_to_user ((struct hd_geometry *) data, &geo,
  142.    sizeof (struct hd_geometry));
  143. if (rc)
  144. rc = -EFAULT;
  145. break;
  146. }
  147. case BIODASDDISABLE:{
  148. if (!capable (CAP_SYS_ADMIN)) {
  149. rc = -EACCES;
  150. break;
  151. }
  152.                         if ( device->level > DASD_STATE_ACCEPT) {
  153.                                 dasd_deactivate_queue(device);
  154.                                 if ( device->request_queue)
  155.                                         dasd_flush_request_queues(device,0);
  156.                                 dasd_flush_chanq(device,0);
  157.                                 dasd_disable_blkdev(device);
  158.                                 dasd_set_device_level (device->devinfo.devno, 
  159.                                                        device->discipline, 
  160.                                                        DASD_STATE_ACCEPT);
  161.                         }
  162.                         break;
  163.         }
  164. case BIODASDENABLE:{
  165.                         dasd_range_t range = { 
  166.                                 from: device->devinfo.devno,
  167.                                 to: device->devinfo.devno 
  168.                         };
  169. if (!capable (CAP_SYS_ADMIN)) {
  170. rc = -EACCES;
  171. break;
  172. }
  173.                         dasd_enable_ranges (&range, device->discipline, 0);
  174.                         break;
  175.         }
  176. case BIODASDFMT:{
  177. /* fdata == NULL is no longer a valid arg to dasd_format ! */
  178. int partn = MINOR (inp->i_rdev) &
  179.     ((1 << major_info->gendisk.minor_shift) - 1);
  180. format_data_t fdata;
  181. if (!capable (CAP_SYS_ADMIN)) {
  182. rc = -EACCES;
  183. break;
  184. }
  185.                         if (dasd_features_from_devno(device->devinfo.devno)&DASD_FEATURE_READONLY) {
  186.                                 rc = -EROFS;
  187.                                 break;
  188.                         }
  189. if (!data) {
  190. rc = -EINVAL;
  191. break;
  192. }
  193. rc = copy_from_user (&fdata, (void *) data,
  194.      sizeof (format_data_t));
  195. if (rc) {
  196. rc = -EFAULT;
  197. break;
  198. }
  199. if (partn != 0) {
  200. DASD_MESSAGE (KERN_WARNING, device, "%s",
  201.       "Cannot low-level format a partition");
  202. return -EINVAL;
  203. }
  204. rc = dasd_format (device, &fdata);
  205. break;
  206. }
  207. case BIODASDPRRST:{     /* reset device profile information */
  208. if (!capable (CAP_SYS_ADMIN)) {
  209. rc = -EACCES;
  210. break;
  211. }
  212. memset (&device->profile, 0,
  213. sizeof (dasd_profile_info_t));
  214. break;
  215. }
  216. case BIODASDPRRD:{      /* retrun device profile information */
  217. rc = copy_to_user((long *)data,
  218.   (long *)&device->profile,
  219.   sizeof(dasd_profile_info_t));
  220. if (rc)
  221. rc = -EFAULT;
  222. break;
  223. }
  224. case BIODASDRSRV:{      /* reserve */
  225. ccw_req_t *req;
  226. if (!capable (CAP_SYS_ADMIN)) {
  227. rc = -EACCES;
  228. break;
  229. }
  230. req = device->discipline->reserve (device);
  231. rc = dasd_sleep_on_req (req);
  232. dasd_free_request (req, device);
  233. break;
  234. }
  235. case BIODASDRLSE:{      /* release */
  236. ccw_req_t *req;
  237. if (!capable (CAP_SYS_ADMIN)) {
  238. rc = -EACCES;
  239. break;
  240. }
  241. req = device->discipline->release (device);
  242. rc = dasd_sleep_on_req (req);
  243. dasd_free_request (req, device);
  244. break;
  245. }
  246. case BIODASDSLCK:{      /* steal lock - unconditional reserve */
  247. ccw_req_t *req;
  248. if (!capable (CAP_SYS_ADMIN)) {
  249. rc = -EACCES;
  250. break;
  251. }
  252. req = device->discipline->steal_lock (device);
  253. rc = dasd_sleep_on_req (req);
  254. dasd_free_request (req, device);
  255. break;
  256. }
  257. case BIODASDINFO:{
  258. dasd_information_t dasd_info;
  259. unsigned long flags;
  260. rc = device->discipline->fill_info (device, &dasd_info);
  261.                         dasd_info.label_block = device->sizes.pt_block;
  262. dasd_info.devno = device->devinfo.devno;
  263. dasd_info.schid = device->devinfo.irq;
  264. dasd_info.cu_type = device->devinfo.sid_data.cu_type;
  265. dasd_info.cu_model = device->devinfo.sid_data.cu_model;
  266. dasd_info.dev_type = device->devinfo.sid_data.dev_type;
  267. dasd_info.dev_model = device->devinfo.sid_data.dev_model;
  268. dasd_info.open_count =
  269.     atomic_read (&device->open_count);
  270. dasd_info.status = device->level;
  271. if (device->discipline) {
  272. memcpy (dasd_info.type,
  273. device->discipline->name, 4);
  274. } else {
  275. memcpy (dasd_info.type, "none", 4);
  276. }
  277. dasd_info.req_queue_len = 0;
  278. dasd_info.chanq_len = 0;
  279. if (device->request_queue->request_fn) {
  280. struct list_head *l;
  281. ccw_req_t *cqr = device->queue.head;
  282. spin_lock_irqsave (&io_request_lock, flags);
  283. list_for_each (l,
  284.        &device->request_queue->
  285.        queue_head) {
  286. dasd_info.req_queue_len++;
  287. }
  288. spin_unlock_irqrestore (&io_request_lock,
  289. flags);
  290. s390irq_spin_lock_irqsave (device->devinfo.irq,
  291.    flags);
  292. while (cqr) {
  293. cqr = cqr->next;
  294. dasd_info.chanq_len++;
  295. }
  296. s390irq_spin_unlock_irqrestore (device->devinfo.
  297. irq, flags);
  298. }
  299. rc =
  300.     copy_to_user ((long *) data, (long *) &dasd_info,
  301.   sizeof (dasd_information_t));
  302. if (rc)
  303. rc = -EFAULT;
  304. break;
  305. }
  306. #if 0 /* needed for XFS */
  307. case BLKBSZSET:{
  308. int bsz;
  309. rc = copy_from_user ((long *)&bsz,(long *)data,sizeof(int));
  310. if ( rc ) {
  311. rc = -EFAULT;
  312. } else {
  313. if ( bsz >= device->sizes.bp_block )
  314. rc = blk_ioctl (inp->i_rdev, no, data);
  315. else
  316. rc = -EINVAL; 
  317. }
  318. break;
  319. }
  320. #endif /* 0 */
  321. case BLKSSZGET:
  322. case BLKROSET:
  323. case BLKROGET:
  324. case BLKRASET:
  325. case BLKRAGET:
  326. case BLKFLSBUF:
  327. case BLKPG:
  328. case BLKELVGET:
  329. case BLKELVSET:
  330. return blk_ioctl (inp->i_rdev, no, data);
  331. break;
  332. default:{
  333. dasd_ioctl_list_t *old = dasd_find_ioctl (no);
  334. if (old) {
  335. if ( old->owner )
  336. __MOD_INC_USE_COUNT(old->owner);
  337. rc = old->handler (inp, no, data);
  338. if ( old->owner )
  339. __MOD_DEC_USE_COUNT(old->owner);
  340. } else {
  341. DASD_MESSAGE (KERN_INFO, device,
  342.       "ioctl 0x%08x=%s'0x%x'%d(%d) data %8lxn",
  343.       no,
  344.       _IOC_DIR (no) == _IOC_NONE ? "0" :
  345.       _IOC_DIR (no) == _IOC_READ ? "r" :
  346.       _IOC_DIR (no) == _IOC_WRITE ? "w" : 
  347.                                               _IOC_DIR (no) == 
  348.                                               (_IOC_READ | _IOC_WRITE) ? "rw" : "u",
  349.                                               _IOC_TYPE (no),
  350.       _IOC_NR (no), 
  351.                                               _IOC_SIZE (no),
  352.       data);
  353. rc = -ENOTTY;
  354. }
  355. break;
  356. }
  357. }
  358. return rc;
  359. }
  360. /* SECTION: The members of the struct file_operations */
  361. static int
  362. dasd_ioctl (struct inode *inp, struct file *filp,
  363.     unsigned int no, unsigned long data)
  364. {
  365. int rc = 0;
  366. if ((!inp) || !(inp->i_rdev)) {
  367. return -EINVAL;
  368. }
  369. rc = do_dasd_ioctl (inp, no, data);
  370. return rc;
  371. }
  372. static int
  373. dasd_open (struct inode *inp, struct file *filp)
  374. {
  375. int rc = 0;
  376.         unsigned long flags;
  377. dasd_device_t *device;
  378. if ((!inp) || !(inp->i_rdev)) {
  379. rc = -EINVAL;
  380.                 goto fail;
  381. }
  382. if (dasd_probeonly) {
  383. printk ("n" KERN_INFO PRINTK_HEADER
  384. "No access to device (%d:%d) due to probeonly moden",
  385. MAJOR (inp->i_rdev), 
  386.                         MINOR (inp->i_rdev));
  387. rc = -EPERM;
  388.                 goto fail;
  389. }
  390.         spin_lock_irqsave(&discipline_lock,flags);
  391. device = dasd_device_from_kdev (inp->i_rdev);
  392. if (!device) {
  393. printk (KERN_WARNING PRINTK_HEADER
  394. "No device registered as (%d:%d)n",
  395. MAJOR (inp->i_rdev), 
  396.                         MINOR (inp->i_rdev));
  397. rc = -ENODEV;
  398.                 goto unlock;
  399. }
  400. if (device->level <= DASD_STATE_ACCEPT ) {
  401. DASD_MESSAGE (KERN_WARNING, device, " %s", 
  402.                               " Cannot open unrecognized devicen");
  403. rc = -ENODEV;
  404.                 goto unlock;
  405. }
  406. if (atomic_inc_return (&device->open_count) == 1 ) {
  407.                 if ( device->discipline->owner )
  408.                         __MOD_INC_USE_COUNT(device->discipline->owner);
  409.         }
  410.  unlock:
  411.         spin_unlock_irqrestore(&discipline_lock,flags);
  412.  fail:
  413. return rc;
  414. }
  415. /*
  416.  * DASD_RELEASE
  417.  *
  418.  * DESCRIPTION
  419.  */
  420. static int
  421. dasd_release (struct inode *inp, struct file *filp)
  422. {
  423. int rc = 0;
  424.         int count;
  425. dasd_device_t *device;
  426. if ((!inp) || !(inp->i_rdev)) {
  427. rc = -EINVAL;
  428.                 goto out;
  429. }
  430. device = dasd_device_from_kdev (inp->i_rdev);
  431. if (!device) {
  432. printk (KERN_WARNING PRINTK_HEADER
  433. "No device registered as %d:%dn",
  434. MAJOR (inp->i_rdev), 
  435.                         MINOR (inp->i_rdev));
  436. rc = -EINVAL;
  437.                 goto out;
  438. }
  439. if (device->level < DASD_STATE_ACCEPT ) {
  440. DASD_MESSAGE (KERN_WARNING, device, " %s",
  441.                               " Cannot release unrecognized devicen");
  442. rc = -ENODEV;
  443.                 goto out;
  444. }
  445.         count = atomic_dec_return (&device->open_count);
  446.         if ( count == 0) {
  447.                 invalidate_buffers (inp->i_rdev);
  448.                 if ( device->discipline->owner )
  449.                         __MOD_DEC_USE_COUNT(device->discipline->owner);
  450. } else if ( count == -1 ) { /* paranoia only */
  451.                 atomic_set (&device->open_count,0);
  452.                 printk (KERN_WARNING PRINTK_HEADER
  453.                         "release called with open count==0n");
  454.         }
  455.  out:
  456. return rc;
  457. }
  458. static struct
  459. block_device_operations dasd_device_operations =
  460. {
  461. owner:THIS_MODULE,
  462. open:dasd_open,
  463. release:dasd_release,
  464. ioctl:dasd_ioctl,
  465. };
  466. /* SECTION: Management of device list */
  467. int
  468. dasd_fillgeo(int kdev,struct hd_geometry *geo)
  469. {
  470. dasd_device_t *device = dasd_device_from_kdev (kdev);
  471. if (!device)
  472.                 return -EINVAL;
  473.         if (!device->discipline->fill_geometry)
  474. return -EINVAL;
  475. device->discipline->fill_geometry (device, geo);
  476. geo->start = device->major_info->gendisk.part[MINOR(kdev)].start_sect 
  477.      >> device->sizes.s2b_shift;;
  478.         return 0;
  479. /* This one is needed for naming 18000+ possible dasd devices */
  480. int
  481. dasd_device_name (char *str, int index, int partition, struct gendisk *hd)
  482. {
  483. int len = 0;
  484. char first, second, third;
  485. if (hd) {
  486. major_info_t *major_info = NULL;
  487. struct list_head *l;
  488. list_for_each (l, &dasd_major_info[0].list) {
  489. major_info = list_entry (l, major_info_t, list);
  490. if (&major_info->gendisk == hd) {
  491. break;
  492. }
  493. index += DASD_PER_MAJOR;
  494. }
  495. if (major_info == &dasd_major_info[0]) {
  496. return -EINVAL;
  497. }
  498. }
  499. third = index % 26;
  500. second = ((index - 26) / 26) % 26;
  501. first = (((index - 702) / 26) / 26) % 26;
  502. len = sprintf (str, "dasd");
  503. if (index > 701) {
  504. len += sprintf (str + len, "%c", first + 'a');
  505. }
  506. if (index > 25) {
  507. len += sprintf (str + len, "%c", second + 'a');
  508. }
  509. len += sprintf (str + len, "%c", third + 'a');
  510. if (partition) {
  511. if (partition > 9) {
  512. return -EINVAL;
  513. } else {
  514. len += sprintf (str + len, "%d", partition);
  515. }
  516. }
  517. str[len] = '';
  518. return 0;
  519. }
  520. static void
  521. dasd_plug_device (dasd_device_t * device)
  522. {
  523. atomic_set(&device->plugged,1);
  524. }
  525. static void
  526. dasd_unplug_device (dasd_device_t * device)
  527. {
  528. atomic_set(&device->plugged,0);
  529.         dasd_schedule_bh(device);
  530. }
  531. static void
  532. dasd_flush_chanq ( dasd_device_t * device, int destroy ) 
  533. {
  534.         ccw_req_t *cqr;
  535.         unsigned long flags;
  536.         if ( destroy ) {
  537.                 s390irq_spin_lock_irqsave (device->devinfo.irq, flags);
  538.                 cqr = device->queue.head;
  539.                 while ( cqr != NULL ) {
  540.                         if ( cqr->status == CQR_STATUS_IN_IO )
  541.                                 device->discipline->term_IO (cqr);
  542.                         if ( cqr->status != CQR_STATUS_DONE ||
  543.                              cqr->status != CQR_STATUS_FAILED ) {
  544.                                 cqr->status = CQR_STATUS_FAILED;
  545.                                 asm volatile ("STCK %0":"=m" (cqr->stopclk));
  546.                         }
  547.                         dasd_schedule_bh(device);
  548.                         cqr = cqr->next;
  549.                 }
  550.                 s390irq_spin_unlock_irqrestore (device->devinfo.irq, flags);
  551.         }
  552.         wait_event( device->wait_q, device->queue.head == NULL );
  553. }
  554. static void
  555. dasd_flush_request_queues ( dasd_device_t * device, int destroy )
  556. {
  557.         int i;
  558.         int major = MAJOR(device->kdev);
  559.         int minor = MINOR(device->kdev);
  560.         for ( i = 0; i < (1 << DASD_PARTN_BITS); i ++) {
  561.                 if ( destroy )
  562.                         destroy_buffers(MKDEV(major,minor+i)); 
  563.                 else
  564.                         invalidate_buffers(MKDEV(major,minor+i)); 
  565.         } 
  566. }
  567. static int
  568. dasd_disable_volume ( dasd_device_t * device, int force ) 
  569. {
  570.         int rc = 0;
  571.         int target  = DASD_STATE_KNOWN;
  572.         int count = atomic_read (&device->open_count);
  573.         
  574. if ( count ) {
  575. DASD_MESSAGE (KERN_EMERG, device, "%s",
  576.       "device has vanished although it was open!");
  577.         }
  578.         if ( force ) {
  579.                 dasd_deactivate_queue(device);
  580.                 dasd_flush_chanq(device,force);
  581.                 dasd_flush_request_queues(device,force);
  582.                 dasd_disable_blkdev(device);
  583.                 target = DASD_STATE_DEL;
  584.         }
  585.         /* unregister partitions ('ungrok_partitions') */
  586.         devfs_register_partitions(&device->major_info->gendisk,
  587.                                   MINOR(device->kdev),1);
  588.         
  589.         DASD_MESSAGE (KERN_WARNING, device, 
  590.                       "disabling device, target state: %d",target);
  591.         dasd_set_device_level (device->devinfo.devno, 
  592.                                device->discipline, 
  593.                                target);
  594.         return rc;
  595. }
  596. static void
  597. dasd_disable_ranges (dasd_range_t *range, 
  598.                      dasd_discipline_t *d,
  599.                      int all, int force ) 
  600. {
  601.         dasd_range_t *rrange;
  602.         int j;
  603.         if (range == &dasd_range_head) {
  604.                 rrange = list_entry (range->list.next, 
  605.                                      dasd_range_t, list);
  606.         } else {
  607.                 rrange = range;
  608.         }
  609.         do {
  610.                 for (j = rrange->from; j <= rrange->to; j++) {
  611.                         dasd_device_t **dptr;
  612.                         dasd_device_t *device;
  613.                         dptr = dasd_device_from_devno(j);
  614.                         if ( dptr == NULL ) {
  615.                             continue;
  616.                         }
  617.                         device = *dptr;
  618.                         if (device == NULL ||
  619.                             (d != NULL &&
  620.                              device -> discipline != d))
  621.                                 continue;
  622.                         
  623.                         dasd_disable_volume(device, force);
  624.                 }
  625.                 rrange = list_entry (rrange->list.next, dasd_range_t, list);
  626.         } while ( all && rrange && rrange != range );
  627. }
  628. static void 
  629. dasd_enable_single_device ( unsigned long arg ) {
  630.         dasd_device_t * device =(dasd_device_t *) arg;
  631.         int devno = device->devinfo.devno;
  632.         dasd_range_t range = { from: devno, to:devno };
  633.         dasd_enable_ranges (&range,NULL,0);
  634. }
  635. static void
  636. dasd_enable_ranges (dasd_range_t *range, dasd_discipline_t *d, int all ) 
  637. {
  638.         int retries = 0;
  639. int j;
  640.         kdev_t tempdev;
  641. dasd_range_t *rrange;
  642. if (range == NULL)
  643. return;
  644.         
  645.         do {
  646.                 if (range == &dasd_range_head) {
  647.                         rrange = list_entry (range->list.next, 
  648.                                              dasd_range_t, list);
  649.                 } else {
  650.                         rrange = range;
  651.                 }
  652.                 do {
  653.                         for (j = rrange->from; j <= rrange->to; j++) {
  654.                                 if ( dasd_devindex_from_devno(j) < 0 )
  655.                                         continue;
  656.                                 dasd_set_device_level (j, d, DASD_STATE_ONLINE);
  657.                         }
  658.                         rrange = list_entry (rrange->list.next, dasd_range_t, list);
  659.                 } while ( all && rrange && rrange != range );
  660.                 if (atomic_read (&dasd_init_pending) == 0) /* we are done, exit loop */
  661.                         break;
  662.                 if ( retries == 0 ) {
  663.                         printk (KERN_INFO PRINTK_HEADER
  664.                                 "waiting for responses...n");
  665.                 } else if ( retries < 5 ) {
  666.                         printk (KERN_INFO PRINTK_HEADER
  667.                                 "waiting a little bit longer...n");
  668.                 } else {
  669.                         printk (KERN_INFO PRINTK_HEADER
  670.                                 "giving up, enable late devices manually!n");
  671.                         break;
  672.                 }
  673.                 interruptible_sleep_on_timeout (&dasd_init_waitq, (1 * HZ));
  674.                 retries ++;
  675.         } while (1);
  676.         /* now setup block devices */
  677.         /* Now do block device and partition setup */
  678.         if (range == &dasd_range_head) {
  679.                 rrange = list_entry (range->list.next, 
  680.                                      dasd_range_t, list);
  681.         } else {
  682.                 rrange = range;
  683.         }
  684.         do {
  685.                 for (j = rrange->from; j <= rrange->to; j++) {
  686.                         dasd_device_t **dptr;
  687.                         dasd_device_t *device;
  688.                         if ( dasd_devindex_from_devno(j) < 0 )
  689.                                 continue;
  690.                         dptr = dasd_device_from_devno(j);
  691.                         device = *dptr;
  692.                         if (device == NULL )
  693.                                 continue;
  694.                         if ( ((d == NULL && device->discipline != NULL) ||
  695.                               (device->discipline == d )) &&
  696.                              device->level >= DASD_STATE_READY &&
  697.                              device->request_queue == NULL ) {
  698.                                 if (dasd_features_from_devno(j)&DASD_FEATURE_READONLY) {
  699.                                         for (tempdev=device->kdev;
  700.                                              tempdev<(device->kdev +(1 << DASD_PARTN_BITS));
  701.                                              tempdev++)
  702.                                                 set_device_ro (tempdev, 1);
  703.                                         printk (KERN_WARNING PRINTK_HEADER 
  704.                                                 "setting read-only mode for device /dev/%sn",
  705.                                                 device->name);
  706.                                 }
  707.                                 dasd_setup_blkdev(device);
  708.                                 dasd_setup_partitions(device);
  709.                         }
  710.                 }
  711.                 rrange = list_entry (rrange->list.next, dasd_range_t, list);
  712.         } while ( all && rrange && rrange != range );
  713. }
  714. #ifdef CONFIG_DASD_DYNAMIC
  715. /*
  716.  * DASD_NOT_OPER_HANDLER
  717.  *
  718.  * DESCRIPTION
  719.  *   handles leaving devices
  720.  */
  721. static void
  722. dasd_not_oper_handler (int irq, int status)
  723. {
  724. dasd_device_t *device = NULL;
  725. major_info_t *major_info = NULL;
  726. struct list_head *l;
  727. int i, devno = -ENODEV;
  728. /* find out devno of leaving device: CIO has already deleted this information ! */
  729. list_for_each (l, &dasd_major_info[0].list) {
  730. major_info = list_entry (l, major_info_t, list);
  731. for (i = 0; i < DASD_PER_MAJOR; i++) {
  732. device = major_info->dasd_device[i];
  733. if (device && device->devinfo.irq == irq) {
  734. devno = device->devinfo.devno;
  735. break;
  736. }
  737. }
  738. if (devno != -ENODEV)
  739. break;
  740. }
  741. DASD_DRIVER_DEBUG_EVENT (5, dasd_not_oper_handler, 
  742.                                  "called for devno %04x", 
  743.                                  devno);
  744. if (devno < 0) {
  745. printk (KERN_WARNING PRINTK_HEADER
  746. "not_oper_handler called on irq 0x%04x no devno!n", 
  747.                         irq);
  748. return;
  749. }
  750.         dasd_disable_volume(device, 1);
  751. }
  752. /*
  753.  * DASD_OPER_HANDLER
  754.  *
  755.  * DESCRIPTION
  756.  *   called by the machine check handler to make an device operational
  757.  */
  758. int
  759. dasd_oper_handler (int irq, devreg_t * devreg)
  760. {
  761. int devno;
  762. int rc = 0;
  763. major_info_t *major_info = NULL;
  764.         dasd_range_t *rptr,range;
  765.         dasd_device_t *device = NULL;
  766. struct list_head *l;
  767.         int i;
  768. devno = get_devno_by_irq (irq);
  769. if (devno == -ENODEV) {
  770. rc = -ENODEV;
  771.                 goto out;
  772. }
  773. DASD_DRIVER_DEBUG_EVENT (5, dasd_oper_handler, 
  774.                                  "called for devno %04x", 
  775.                                  devno);
  776. /* find out devno of device */
  777. list_for_each (l, &dasd_major_info[0].list) {
  778. major_info = list_entry (l, major_info_t, list);
  779. for (i = 0; i < DASD_PER_MAJOR; i++) {
  780. device = major_info->dasd_device[i];
  781. if (device && device->devinfo.irq == irq) {
  782. devno = device->devinfo.devno;
  783. break;
  784. }
  785. }
  786. if (devno != -ENODEV)
  787. break;
  788. }
  789. if (devno < 0) {
  790.                 BUG();
  791. }
  792.         if ( device &&
  793.              device->level == DASD_STATE_READY ) {
  794.             dasd_set_device_level (device->devinfo.devno, 
  795.                                    device->discipline, DASD_STATE_ONLINE);
  796.         } else {
  797.             if (dasd_autodetect) {
  798. rptr = dasd_add_range (devno, devno, DASD_DEFAULT_FEATURES);
  799.                 if ( rptr == NULL ) {
  800.                     rc = -ENOMEM;
  801.                     goto out;
  802.                 }
  803.             } else {
  804.                 range.from = devno;
  805.                 range.to = devno;
  806.                 rptr = &range;
  807.             }
  808.             dasd_enable_ranges (rptr, NULL, 0);
  809.         }
  810.  out:
  811. return rc;
  812. }
  813. #endif /* CONFIG_DASD_DYNAMIC */
  814. static inline dasd_device_t **
  815. dasd_find_device_addr ( int devno ) 
  816. {
  817.         dasd_device_t **device_addr;
  818. DASD_DRIVER_DEBUG_EVENT (1, dasd_find_device_addr, 
  819.                                  "devno %04x", 
  820.                                  devno);
  821. if ( dasd_devindex_from_devno (devno) < 0 ) {
  822.                 DASD_DRIVER_DEBUG_EXCEPTION (1, dasd_find_device_addr, 
  823.                                              "no dasd: devno %04x",
  824.                                              devno);
  825. return NULL;
  826. }
  827.         /* allocate major numbers on demand  for new devices */
  828. while ((device_addr = dasd_device_from_devno (devno)) == NULL) {
  829.                 int rc;
  830. if ((rc = dasd_register_major (NULL)) <= 0) {
  831.                         DASD_DRIVER_DEBUG_EXCEPTION (1, dasd_find_device_addr, 
  832.                                                      "%s",
  833.                                                      "out of major numbers!");
  834.                         break;
  835. }
  836. }
  837.         return device_addr;
  838. }
  839. static inline int
  840. dasd_state_del_to_new (dasd_device_t **addr ) 
  841. {
  842.         dasd_device_t* device;
  843.         int rc = 0;
  844. if (*addr == NULL) { /* allocate device descriptor on demand for new device */
  845.                 device = kmalloc (sizeof (dasd_device_t), GFP_ATOMIC);
  846. if (device == NULL ) {
  847. rc = -ENOMEM;
  848.                         goto out;
  849. }
  850. memset (device, 0, sizeof (dasd_device_t));
  851.                 *addr = device;
  852.                 device->lowmem_ccws = (void*)get_free_page (GFP_ATOMIC|GFP_DMA);
  853.                 if (device->lowmem_ccws == NULL) {
  854.                         rc = -ENOMEM;
  855.                         goto noccw;
  856. }
  857. #ifdef CONFIG_ARCH_S390X
  858.                 device->lowmem_idals =
  859.                     device->lowmem_idal_ptr = (void*) get_free_page (GFP_ATOMIC|GFP_DMA);
  860.                 if (device->lowmem_idals == NULL) {
  861.                         rc = -ENOMEM;
  862.                         goto noidal;
  863.                 }                
  864. #endif
  865. }
  866.         goto out;
  867. #ifdef CONFIG_ARCH_S390X
  868.  noidal:
  869.         free_page ((long) device->lowmem_ccws);
  870. #endif
  871.  noccw:
  872.         kfree(device);
  873.  out:
  874.         return rc;
  875. }
  876. static inline int
  877. dasd_state_new_to_del (dasd_device_t **addr )
  878. {
  879.         dasd_device_t *device = *addr;
  880.         if (device && device->private) {
  881.                 kfree(device->private);
  882.                 device->private = NULL;
  883.         }
  884. #ifdef CONFIG_ARCH_S390X
  885.         free_page ((long)(device->lowmem_idals));
  886. #endif
  887.         free_page((long)(device->lowmem_ccws));
  888.         kfree(device);
  889.         *addr = NULL; 
  890.         return 0;
  891. }
  892. static inline int
  893. dasd_state_new_to_known (dasd_device_t **dptr, int devno, dasd_discipline_t *disc) 
  894. {
  895.         int rc = 0;
  896. umode_t devfs_perm  = S_IFBLK | S_IRUSR | S_IWUSR;
  897.         struct list_head *l;
  898.         major_info_t *major_info = NULL;
  899.         int i;
  900.         dasd_device_t *device = *dptr;
  901.         devfs_handle_t dir;
  902.         char buffer[5];
  903.         
  904. list_for_each (l, &dasd_major_info[0].list) {
  905.                 major_info = list_entry (l, major_info_t, list);
  906. for (i = 0; i < DASD_PER_MAJOR; i++) {
  907. if (major_info->dasd_device[i] == device) {
  908. device->kdev = MKDEV (major_info->gendisk.major,
  909.                                                       i << DASD_PARTN_BITS);
  910. break;
  911. }
  912. }
  913. if (i < DASD_PER_MAJOR) /* we found one */
  914. break;
  915. }
  916.         if ( major_info == NULL || major_info == &dasd_major_info[0] ) 
  917.                 BUG();
  918.         device->major_info = major_info;
  919.         dasd_device_name (device->name,
  920.                           (((long)dptr -
  921.                             (long)device->major_info->dasd_device) /
  922.                            sizeof (dasd_device_t *)),
  923.                           0, &device->major_info->gendisk);
  924.         init_waitqueue_head (&device->wait_q);
  925.         
  926.         rc = get_dev_info_by_devno (devno, &device->devinfo);
  927.         if ( rc ) {
  928.                 goto out;
  929.         }
  930. DASD_DRIVER_DEBUG_EVENT (5, dasd_state_new_to_known, 
  931.                                  "got devinfo CU-type %04x and dev-type %04x", 
  932.                                  device->devinfo.sid_data.cu_type,
  933.                                  device->devinfo.sid_data.dev_type);
  934.         if ( devno != device->devinfo.devno )
  935.                 BUG();
  936.         device->discipline = dasd_find_disc (device, disc);
  937.         if ( device->discipline == NULL ) {
  938.                 rc = -ENODEV;
  939.                 goto out;
  940.         }
  941.         sprintf (buffer, "%04x", 
  942.                  device->devinfo.devno);
  943.         dir = devfs_mk_dir (dasd_devfs_handle, buffer, device);
  944.         device->major_info->gendisk.de_arr[MINOR(device->kdev)
  945.                                           >> DASD_PARTN_BITS] = dir;
  946. if (dasd_features_from_devno(device->devinfo.devno)&DASD_FEATURE_READONLY) {
  947.         devfs_perm &= ~(S_IWUSR);
  948. }
  949.         device->devfs_entry = devfs_register (dir,"device",DEVFS_FL_DEFAULT,
  950.                                               MAJOR(device->kdev),
  951.                                               MINOR(device->kdev),
  952.                                               devfs_perm,
  953.                                               &dasd_device_operations,NULL);
  954.         device->level = DASD_STATE_KNOWN;
  955.  out:
  956.         return rc;
  957. }
  958. static inline int
  959. dasd_state_known_to_new (dasd_device_t *device ) 
  960. {
  961.         int rc = 0;
  962.         /* don't reset to zeros because of persistent data durich detach/attach! */
  963.         devfs_unregister(device->devfs_entry);
  964.         devfs_unregister(device->major_info->gendisk.de_arr[MINOR(device->kdev) >> DASD_PARTN_BITS]);
  965.         return rc;
  966. }
  967. static inline int
  968. dasd_state_known_to_accept (dasd_device_t *device) 
  969. {
  970.         int rc = 0;
  971.         device->debug_area = debug_register (device->name, 0, 2, 
  972.                                              3 * sizeof (long));
  973.         debug_register_view (device->debug_area, &debug_sprintf_view);
  974.         debug_register_view (device->debug_area, &debug_hex_ascii_view);
  975.         DASD_DEVICE_DEBUG_EVENT (0, device,"%p debug area created",
  976.                                  device);
  977.         
  978.         if (device->discipline->int_handler) {
  979.                 rc = s390_request_irq_special (device->devinfo.irq,
  980.                                                device->discipline->int_handler,
  981.                                                dasd_not_oper_handler,
  982.                                                0, DASD_NAME,
  983.                                                &device->dev_status);
  984.                 if ( rc ) {
  985.                         printk("No request IRQn");
  986.                         goto out;
  987.                 }
  988.         }
  989.         device->level = DASD_STATE_ACCEPT;
  990.  out:
  991.         return rc;
  992. }
  993. static inline int
  994. dasd_state_accept_to_known (dasd_device_t *device ) 
  995. {
  996.         if ( device->discipline == NULL )
  997.                 goto out;
  998.         if (device->discipline->int_handler) {
  999.                 free_irq (device->devinfo.irq, &device->dev_status);
  1000.         }
  1001.         DASD_DEVICE_DEBUG_EVENT (0, device,"%p debug area deleted",
  1002.                                  device);
  1003.         if ( device->debug_area != NULL )
  1004.                 debug_unregister (device->debug_area);
  1005.         device->discipline = NULL;
  1006.         device->level = DASD_STATE_KNOWN;
  1007.  out:
  1008.         return 0;
  1009. }
  1010. static inline int
  1011. dasd_state_accept_to_init (dasd_device_t *device) 
  1012. {
  1013.         int rc = 0;
  1014.         unsigned long flags;
  1015.         if ( device->discipline->init_analysis ) {
  1016.                 device->init_cqr=device->discipline->init_analysis (device);
  1017.                 if ( device->init_cqr != NULL ) {
  1018.                         if ( device->discipline->start_IO == NULL )
  1019.                                 BUG();
  1020.                         atomic_inc (&dasd_init_pending);
  1021.                         s390irq_spin_lock_irqsave (device->devinfo.irq, 
  1022.                                                    flags);
  1023.                         rc = device->discipline->start_IO (device->init_cqr);
  1024.                         s390irq_spin_unlock_irqrestore(device->devinfo.irq, 
  1025.                                                        flags);
  1026.                         if ( rc )
  1027.                                 goto out;
  1028.                         device->level = DASD_STATE_INIT;
  1029.                 } else {
  1030.                         rc = -ENOMEM;
  1031.                 }
  1032.         } else {
  1033.                 rc = dasd_state_init_to_ready ( device ); 
  1034.         }
  1035.  out:
  1036.         return rc;
  1037. }
  1038. static inline int
  1039. dasd_state_init_to_ready (dasd_device_t *device ) 
  1040. {
  1041.         int rc = 0;    
  1042.         if (device->discipline->do_analysis != NULL)
  1043.                 if ( device->discipline->do_analysis (device) == 0 ) 
  1044.                         switch (device->sizes.bp_block) {
  1045.                         case 512:
  1046.                         case 1024:
  1047.                         case 2048:
  1048.                         case 4096:
  1049.                                 break;
  1050.                         default:
  1051.                                 rc = -EMEDIUMTYPE;
  1052.                         }
  1053.         if ( device->init_cqr ) {
  1054.                 /* This pointer is no longer needed, BUT dont't free the       */ 
  1055.                 /* memory, because this is done in bh for finished request!!!! */
  1056.                 atomic_dec(&dasd_init_pending);
  1057.                 device->init_cqr = NULL; 
  1058.         }
  1059.         device->level = DASD_STATE_READY;
  1060.         return rc;
  1061. }
  1062. static inline int
  1063. dasd_state_ready_to_accept (dasd_device_t *device ) 
  1064. {
  1065.         int rc = 0;
  1066.         unsigned long flags;
  1067.         s390irq_spin_lock_irqsave (device->devinfo.irq, flags);
  1068.         if ( device->init_cqr != NULL &&  atomic_read(&dasd_init_pending) != 0 ) {
  1069.                 if ( device->discipline->term_IO == NULL )
  1070.                         BUG();
  1071.                 device->discipline->term_IO (device->init_cqr);
  1072.                 atomic_dec (&dasd_init_pending);
  1073.                 dasd_free_request (device->init_cqr, device);
  1074.                 device->init_cqr = NULL;
  1075.         }
  1076.         s390irq_spin_unlock_irqrestore(device->devinfo.irq, flags);
  1077.         memset(&device->sizes,0,sizeof(dasd_sizes_t));
  1078.         device->level = DASD_STATE_ACCEPT;
  1079.         return rc;
  1080. }
  1081. static inline int
  1082. dasd_state_ready_to_online (dasd_device_t *device ) 
  1083. {
  1084.         int rc = 0;
  1085.         dasd_unplug_device (device);
  1086.         device->level = DASD_STATE_ONLINE;
  1087.         return rc;
  1088. }
  1089. static inline int
  1090. dasd_state_online_to_ready (dasd_device_t *device ) 
  1091. {
  1092.         int rc = 0;
  1093.         dasd_plug_device (device);
  1094.         device->level = DASD_STATE_READY;
  1095.         return rc;
  1096. }
  1097. static inline int
  1098. dasd_setup_blkdev (dasd_device_t *device ) 
  1099. {
  1100.         int rc = 0;
  1101.         int i;
  1102.         int major = MAJOR(device->kdev);
  1103.         int minor = MINOR(device->kdev);
  1104.         for (i = 0; i < (1 << DASD_PARTN_BITS); i++) {
  1105.                 if (i == 0)
  1106.                         device->major_info->gendisk.sizes[minor] =
  1107.                                 (device->sizes.blocks << device->
  1108.                                  sizes.s2b_shift) >> 1;
  1109.                 else
  1110.                         device->major_info->gendisk.sizes[minor + i] = 0;
  1111.                 hardsect_size[major][minor + i] = device->sizes.bp_block;
  1112.                 blksize_size[major][minor + i] = device->sizes.bp_block;
  1113.                 max_sectors[major][minor + i] =
  1114.                         device->discipline->max_blocks << 
  1115.                         device->sizes.s2b_shift;
  1116. device->major_info->gendisk.part[minor+i].start_sect = 0;
  1117. device->major_info->gendisk.part[minor+i].nr_sects = 0;
  1118.         }
  1119.         device->request_queue = kmalloc(sizeof(request_queue_t),GFP_KERNEL);
  1120.         device->request_queue->queuedata = device;
  1121.         blk_init_queue (device->request_queue, do_dasd_request);
  1122.         blk_queue_headactive (device->request_queue, 0);
  1123.         elevator_init (&(device->request_queue->elevator),ELEVATOR_NOOP);
  1124.         return rc;
  1125. }
  1126. static void
  1127. dasd_deactivate_queue (dasd_device_t *device)
  1128. {
  1129.         int i;
  1130.         int minor = MINOR(device->kdev);
  1131.         for (i = 0; i < (1 << DASD_PARTN_BITS); i++) {
  1132.                 device->major_info->gendisk.sizes[minor + i] = 0;
  1133.         }
  1134. }
  1135. static inline int
  1136. dasd_disable_blkdev (dasd_device_t *device ) 
  1137. {
  1138.         int i;
  1139.         int major = MAJOR(device->kdev);
  1140.         int minor = MINOR(device->kdev);
  1141.         for (i = 0; i < (1 << DASD_PARTN_BITS); i++) {
  1142.                 destroy_buffers(MKDEV(major,minor+i));
  1143.                 device->major_info->gendisk.sizes[minor + i] = 0;
  1144.                 hardsect_size[major][minor + i] = 0;
  1145.                 blksize_size[major][minor + i] = 0;
  1146.                 max_sectors[major][minor + i] = 0;
  1147.         }
  1148.         if (device->request_queue) {
  1149.             blk_cleanup_queue (device->request_queue);
  1150.             kfree(device->request_queue);
  1151.             device->request_queue = NULL;
  1152.         }
  1153.         return 0;
  1154. }
  1155. /*
  1156.  * function dasd_setup_partitions
  1157.  * calls the function in genhd, which is appropriate to setup a partitioned disk
  1158.  */
  1159. static inline void
  1160. dasd_setup_partitions ( dasd_device_t * device ) 
  1161. {
  1162. register_disk (&device->major_info->gendisk,
  1163.                        device->kdev,
  1164.        1 << DASD_PARTN_BITS,
  1165.        &dasd_device_operations,
  1166.        (device->sizes.blocks << device->sizes.s2b_shift));
  1167. }
  1168. static inline void
  1169. dasd_destroy_partitions ( dasd_device_t * device ) 
  1170. {
  1171.         int i;
  1172.         int minor = MINOR(device->kdev);
  1173.         
  1174.         for (i = 0; i < (1 << DASD_PARTN_BITS); i++) {
  1175.                 device->major_info->gendisk.part[minor+i].start_sect = 0;
  1176.                 device->major_info->gendisk.part[minor+i].nr_sects   = 0;
  1177.         }
  1178.         devfs_register_partitions(&device->major_info->gendisk,
  1179.                                   MINOR(device->kdev),1);
  1180. }
  1181. static inline void
  1182. dasd_resetup_partitions ( dasd_device_t * device ) 
  1183. {
  1184.     BUG();
  1185.     dasd_destroy_partitions ( device ) ;
  1186.     dasd_setup_partitions ( device ) ;
  1187. }
  1188. /*
  1189.  * function dasd_set_device_level
  1190.  */
  1191. static int
  1192. dasd_set_device_level (unsigned int devno, 
  1193.                        dasd_discipline_t * discipline,
  1194.                        int to_state)
  1195. {
  1196. int rc = 0;
  1197.         dasd_device_t **device_addr;
  1198.         dasd_device_t *device;
  1199.         int from_state;
  1200.         device_addr = dasd_find_device_addr ( devno );
  1201.         if ( device_addr == NULL ) {
  1202.                 rc = -ENODEV;
  1203.                 goto out;
  1204.         }
  1205.         device = *device_addr;
  1206.         if ( device == NULL ) {
  1207.                 from_state = DASD_STATE_DEL;
  1208.                 if ( to_state == DASD_STATE_DEL )
  1209.                         goto out;
  1210.         } else {
  1211.                 from_state = device->level;
  1212.         }
  1213.         DASD_DRIVER_DEBUG_EVENT (3, dasd_set_device_level,
  1214.                                  "devno %04x; from %i to %i",
  1215.                                  devno,
  1216.                                  from_state,
  1217.                                  to_state);
  1218.         if ( from_state == to_state )
  1219.                 goto out;
  1220.         if ( to_state < from_state )
  1221.                 goto shutdown;
  1222.         /* First check for bringup */
  1223.         if ( from_state <= DASD_STATE_DEL &&
  1224.              to_state >= DASD_STATE_NEW ) { 
  1225.                 rc = dasd_state_del_to_new(device_addr);
  1226.                 if ( rc ) {
  1227.                         goto bringup_fail;
  1228.                 }
  1229.                 device = *device_addr;
  1230.         }
  1231.         if ( from_state <= DASD_STATE_NEW &&
  1232.              to_state >= DASD_STATE_KNOWN ) { 
  1233.                 rc = dasd_state_new_to_known( device_addr, devno, discipline );
  1234.                 if ( rc ) {
  1235.                         goto bringup_fail;
  1236.                 }
  1237.         }
  1238.         if ( from_state <= DASD_STATE_KNOWN &&
  1239.              to_state >= DASD_STATE_ACCEPT ) { 
  1240.                 rc = dasd_state_known_to_accept(device);
  1241.                 if ( rc ) {
  1242.                         goto bringup_fail;
  1243.                 }
  1244.         }
  1245.         if ( dasd_probeonly ) {
  1246.             goto out;
  1247.         }
  1248.         if ( from_state <= DASD_STATE_ACCEPT &&
  1249.              to_state >= DASD_STATE_INIT ) { 
  1250.                 rc = dasd_state_accept_to_init(device);
  1251.                 if ( rc ) {
  1252.                         goto bringup_fail;
  1253.                 }
  1254.         }
  1255.         if ( from_state <= DASD_STATE_INIT &&
  1256.              to_state >= DASD_STATE_READY ) { 
  1257.                 rc = -EAGAIN;
  1258.                 goto out;
  1259.         }
  1260.         if ( from_state <= DASD_STATE_READY &&
  1261.              to_state >= DASD_STATE_ONLINE ) { 
  1262.                 rc = dasd_state_ready_to_online(device);
  1263.                 if ( rc ) {
  1264.                         goto bringup_fail;
  1265.                 }
  1266.         }
  1267.         goto out;
  1268.  bringup_fail:   /* revert changes */
  1269. #if 0
  1270.         printk (KERN_DEBUG PRINTK_HEADER
  1271.                 "failed to set device from state %d to %d at "
  1272.                 "level %d rc %d. Reverting...n",
  1273.                 from_state,
  1274.                 to_state,
  1275.                 device->level,
  1276.                 rc);
  1277. #endif
  1278.         to_state = from_state;
  1279.         from_state = device->level;
  1280.         
  1281.         /* now do a shutdown */
  1282.  shutdown: 
  1283.         if ( from_state >= DASD_STATE_ONLINE &&
  1284.              to_state <= DASD_STATE_READY ) 
  1285.                 if (dasd_state_online_to_ready(device))
  1286.                         BUG();
  1287.         if ( from_state >= DASD_STATE_READY &&
  1288.              to_state <= DASD_STATE_ACCEPT ) 
  1289.                 if ( dasd_state_ready_to_accept(device))
  1290.                         BUG();
  1291.         if ( from_state >= DASD_STATE_ACCEPT &&
  1292.              to_state <= DASD_STATE_KNOWN ) 
  1293.                 if ( dasd_state_accept_to_known(device))
  1294.                         BUG();
  1295.         if ( from_state >= DASD_STATE_KNOWN &&
  1296.              to_state <= DASD_STATE_NEW ) 
  1297.                 if ( dasd_state_known_to_new(device))
  1298.                         BUG();
  1299.         if ( from_state >= DASD_STATE_NEW &&
  1300.              to_state <= DASD_STATE_DEL) 
  1301.                 if (dasd_state_new_to_del(device_addr))
  1302.                         BUG();
  1303.         goto out;
  1304.  out:
  1305.         return rc;
  1306. }
  1307. /* SECTION: Procfs stuff */
  1308. typedef struct {
  1309. char *data;
  1310. int len;
  1311. } tempinfo_t;
  1312. void
  1313. dasd_fill_inode (struct inode *inode, int fill)
  1314. {
  1315. if (fill)
  1316. MOD_INC_USE_COUNT;
  1317. else
  1318. MOD_DEC_USE_COUNT;
  1319. }
  1320. static struct proc_dir_entry *dasd_proc_root_entry = NULL;
  1321. static struct proc_dir_entry *dasd_devices_entry;
  1322. static struct proc_dir_entry *dasd_statistics_entry;
  1323. static int
  1324. dasd_devices_open (struct inode *inode, struct file *file)
  1325. {
  1326. int rc = 0;
  1327. int size = 1;
  1328. int len = 0;
  1329. major_info_t *temp = NULL;
  1330. struct list_head *l;
  1331. tempinfo_t *info;
  1332. int i;
  1333.         unsigned long flags;
  1334.         int index = 0;
  1335.         MOD_INC_USE_COUNT;
  1336.         spin_lock_irqsave(&discipline_lock,flags);
  1337. info = (tempinfo_t *) vmalloc (sizeof (tempinfo_t));
  1338. if (info == NULL) {
  1339.                 printk (KERN_WARNING "No memory available for datan");
  1340.                 MOD_DEC_USE_COUNT;
  1341.                 return -ENOMEM;
  1342. } else {
  1343. file->private_data = (void *) info;
  1344. }
  1345. list_for_each (l, &dasd_major_info[0].list) {
  1346.                 size += 128 * 1 << (MINORBITS - DASD_PARTN_BITS);
  1347. }
  1348. info->data = (char *) vmalloc (size);
  1349. DASD_DRIVER_DEBUG_EVENT (1, dasd_devices_open, "area: %p, size 0x%x",
  1350.  info->data, 
  1351.                                  size);
  1352. if (size && info->data == NULL) {
  1353. printk (KERN_WARNING "No memory available for datan");
  1354. vfree (info);
  1355.                 MOD_DEC_USE_COUNT;
  1356. return -ENOMEM;
  1357. }
  1358. list_for_each (l, &dasd_major_info[0].list) {
  1359. temp = list_entry (l, major_info_t, list);
  1360. for (i = 0; i < 1 << (MINORBITS - DASD_PARTN_BITS); i++) {
  1361. dasd_device_t *device;
  1362.                         int devno = dasd_devno_from_devindex(index+i);
  1363.                         int features;
  1364.                         if ( devno == -ENODEV )
  1365.                                 continue;
  1366.                         features = dasd_features_from_devno(devno);
  1367.                         if (features < DASD_DEFAULT_FEATURES)
  1368.                                 features = DASD_DEFAULT_FEATURES;
  1369.                         device = temp->dasd_device[i];
  1370. if (device) {
  1371. len += sprintf (info->data + len,
  1372. "%04x(%s) at (%3d:%3d) is %-7s%4s: ",
  1373. device->devinfo.devno,
  1374. device->discipline ?
  1375. device->
  1376. discipline->name : "none",
  1377. temp->gendisk.major,
  1378. i << DASD_PARTN_BITS,
  1379. device->name,
  1380.                                                 (features & DASD_FEATURE_READONLY) ? 
  1381.                                                 "(ro)" : " ");
  1382.                                 
  1383. switch (device->level) {
  1384. case DASD_STATE_NEW:
  1385.                                         len +=
  1386.     sprintf (info->data + len,
  1387.      "new");
  1388.                                         break;
  1389. case DASD_STATE_KNOWN:
  1390. len +=
  1391.     sprintf (info->data + len,
  1392.      "detected");
  1393. break;
  1394. case DASD_STATE_ACCEPT:
  1395.                                         len += sprintf (info->data + len,"accepted");
  1396. break;
  1397. case DASD_STATE_INIT:
  1398. len +=
  1399.     sprintf (info->data + len,
  1400.      "busy   ");
  1401. break;
  1402. case DASD_STATE_READY:
  1403. case DASD_STATE_ONLINE:
  1404.                                     if ( atomic_read(&device->plugged) )
  1405.                                         len +=
  1406.                                             sprintf (info->data + len,
  1407.                                                      "fenced ");
  1408.                                     else
  1409.                                         len +=
  1410.                                             sprintf (info->data + len,
  1411.                                                      "active ");
  1412.                                     if ( device->sizes.bp_block == 512 ||
  1413.                                          device->sizes.bp_block == 1024 ||
  1414.                                          device->sizes.bp_block == 2048 ||
  1415.                                          device->sizes.bp_block == 4096 )
  1416. len +=
  1417.     sprintf (info->data + len,
  1418.      "at blocksize: %d, %ld blocks, %ld MB",
  1419.      device->sizes.bp_block,
  1420.      device->sizes.blocks,
  1421.      ((device->
  1422.        sizes.bp_block >> 9) *
  1423.       device->sizes.
  1424.       blocks) >> 11);
  1425.                                     else
  1426.                                         len +=
  1427.                                             sprintf (info->data + len,
  1428.                                                      "n/f    ");
  1429. break;
  1430. default:
  1431. len +=
  1432.     sprintf (info->data + len,
  1433.      "no stat");
  1434. break;
  1435. }
  1436. } else {
  1437.                                 char buffer[7];
  1438.                                 dasd_device_name (buffer, i, 0, &temp->gendisk);
  1439.                                 if ( devno < 0  ) {
  1440.                                         len += sprintf (info->data + len,
  1441.                                                         "none");
  1442.                                 } else {
  1443.                                         len += sprintf (info->data + len,
  1444.                                                         "%04x",devno);
  1445.                                 }
  1446.                                 len += sprintf (info->data + len,
  1447.                                                 "(none) at (%3d:%3d) is %-7s%4s: unknown",
  1448. temp->gendisk.major,
  1449. i << DASD_PARTN_BITS,
  1450. buffer,
  1451.                                                 (features & DASD_FEATURE_READONLY) ? 
  1452.                                                 "(ro)" : " ");
  1453.                         }
  1454.                         if ( dasd_probeonly )
  1455.                             len += sprintf(info->data + len,"(probeonly)");
  1456.                         len += sprintf(info->data + len,"n");
  1457. }
  1458.                 index += 1 << (MINORBITS - DASD_PARTN_BITS);
  1459. }
  1460. info->len = len;
  1461.         spin_unlock_irqrestore(&discipline_lock,flags);
  1462. return rc;
  1463. }
  1464. #define MIN(a,b) ((a)<(b)?(a):(b))
  1465. static ssize_t
  1466. dasd_generic_read (struct file *file, char *user_buf, size_t user_len,
  1467.    loff_t * offset)
  1468. {
  1469. loff_t len;
  1470. tempinfo_t *p_info = (tempinfo_t *) file->private_data;
  1471. if (*offset >= p_info->len) {
  1472. return 0; /* EOF */
  1473. } else {
  1474. len = MIN (user_len, (p_info->len - *offset));
  1475. if (copy_to_user (user_buf, &(p_info->data[*offset]), len))
  1476. return -EFAULT;
  1477. (*offset) += len;
  1478. return len; /* number of bytes "read" */
  1479. }
  1480. }
  1481. static ssize_t
  1482. dasd_devices_write (struct file *file, const char *user_buf,
  1483.     size_t user_len, loff_t * offset)
  1484. {
  1485. char *buffer;
  1486. int off = 0;
  1487. char *temp;
  1488. dasd_range_t range;
  1489.         int features;
  1490. if (user_len > PAGE_SIZE)
  1491. return -EINVAL;
  1492. buffer = vmalloc (user_len+1);
  1493. if (buffer == NULL)
  1494. return -ENOMEM;
  1495. if (copy_from_user (buffer, user_buf, user_len)) {
  1496. vfree (buffer);
  1497. return -EFAULT;
  1498. }
  1499.         /* replace LF with '' */
  1500.         if (buffer[user_len -1] == 'n') {
  1501.                 buffer[user_len -1] = '';
  1502.         } else {
  1503.                 buffer[user_len] = '';
  1504.         }
  1505. printk (KERN_INFO PRINTK_HEADER "/proc/dasd/devices: '%s'n", buffer);
  1506. if (strncmp (buffer, "set ", 4) && strncmp (buffer, "add ", 4)) {
  1507. printk (KERN_WARNING PRINTK_HEADER
  1508. "/proc/dasd/devices: only 'set' and 'add' are supported verbsn");
  1509. return -EINVAL;
  1510. }
  1511. off += 4;
  1512. while (buffer[off] && !isalnum (buffer[off]))
  1513. off++;
  1514. if (!strncmp (buffer + off, "device", strlen ("device"))) {
  1515. off += strlen ("device");
  1516. while (buffer[off] && !isalnum (buffer[off]))
  1517. off++;
  1518. }
  1519. if (!strncmp (buffer + off, "range=", strlen ("range="))) {
  1520. off += strlen ("range=");
  1521. while (buffer[off] && !isalnum (buffer[off]))
  1522. off++;
  1523. }
  1524. temp = buffer + off;
  1525. range.from = dasd_strtoul (temp, &temp, &features);
  1526. range.to = range.from;
  1527. if (*temp == '-') {
  1528. temp++;
  1529. range.to = dasd_strtoul (temp, &temp, &features);
  1530. }
  1531.         if (range.from == -EINVAL ||
  1532.             range.to   == -EINVAL   ) {
  1533.                 
  1534.                 printk (KERN_WARNING PRINTK_HEADER
  1535.                         "/proc/dasd/devices: range parse error in '%s'n", 
  1536.                         buffer);
  1537.         } else {
  1538.                 off = (long) temp - (long) buffer;
  1539.                 if (!strncmp (buffer, "add", strlen ("add"))) {
  1540.                         dasd_add_range (range.from, range.to, features);
  1541.                         dasd_enable_ranges (&range, NULL, 0);
  1542.                 } else { 
  1543.                         while (buffer[off] && !isalnum (buffer[off]))
  1544.                                 off++;
  1545.                         if (!strncmp (buffer + off, "on", strlen ("on"))) {
  1546.                                 dasd_enable_ranges (&range, NULL, 0);
  1547.                         } else if (!strncmp (buffer + off, "off", strlen ("off"))) {
  1548.                                 dasd_disable_ranges (&range, NULL, 0, 1);
  1549.                         } else {
  1550.                                 printk (KERN_WARNING PRINTK_HEADER
  1551.                                         "/proc/dasd/devices: parse error in '%s'n",
  1552.                                         buffer);
  1553.                         }
  1554.                 }
  1555.         }
  1556. vfree (buffer);
  1557. return user_len;
  1558. }
  1559. static int
  1560. dasd_devices_close (struct inode *inode, struct file *file)
  1561. {
  1562. int rc = 0;
  1563. tempinfo_t *p_info = (tempinfo_t *) file->private_data;
  1564. if (p_info) {
  1565. if (p_info->data)
  1566. vfree (p_info->data);
  1567. vfree (p_info);
  1568. }
  1569. MOD_DEC_USE_COUNT;
  1570. return rc;
  1571. }
  1572. static struct file_operations dasd_devices_file_ops = {
  1573. read:dasd_generic_read, /* read */
  1574. write:dasd_devices_write, /* write */
  1575. open:dasd_devices_open, /* open */
  1576. release:dasd_devices_close, /* close */
  1577. };
  1578. static struct inode_operations dasd_devices_inode_ops = {
  1579. };
  1580. static int
  1581. dasd_statistics_open (struct inode *inode, struct file *file)
  1582. {
  1583. int rc = 0;
  1584. int len = 0;
  1585. tempinfo_t *info;
  1586. int shift, i, help = 0;
  1587.         MOD_INC_USE_COUNT;
  1588. info = (tempinfo_t *) vmalloc (sizeof (tempinfo_t));
  1589. if (info == NULL) {
  1590. printk (KERN_WARNING "No memory available for datan");
  1591.                 MOD_DEC_USE_COUNT;
  1592. return -ENOMEM;
  1593. } else {
  1594. file->private_data = (void *) info;
  1595. }
  1596. info->data = (char *) vmalloc (PAGE_SIZE); /* FIXME! determine space needed in a better way */
  1597. if (info->data == NULL) {
  1598. printk (KERN_WARNING "No memory available for datan");
  1599. vfree (info);
  1600. file->private_data = NULL;
  1601.                 MOD_DEC_USE_COUNT;
  1602. return -ENOMEM;
  1603. }
  1604.         
  1605.         /* prevent couter 'ouverflow' on output */
  1606. for (shift = 0, help = dasd_global_profile.dasd_io_reqs;
  1607.      help > 9999999; help = help >> 1, shift++) ;
  1608. len = sprintf (info->data, "%d dasd I/O requestsn",
  1609.                        dasd_global_profile.dasd_io_reqs);
  1610. len += sprintf (info->data + len, "with %d sectors(512B each)n",
  1611.                         dasd_global_profile.dasd_io_sects);
  1612. len += sprintf (info->data + len,
  1613.                         "   __<4    ___8    __16    __32    __64 "
  1614.                         "   _128    _256    _512    __1k    __2k "
  1615.                         "   __4k    __8k    _16k    _32k    _64k "
  1616.                         "   128kn");
  1617. len += sprintf (info->data + len,
  1618.                         "   _256    _512    __1M    __2M    __4M "
  1619.                         "   __8M    _16M    _32M    _64M    128M "
  1620.                         "   256M    512M    __1G    __2G    __4G "
  1621.                         "   _>4Gn");
  1622. len += sprintf (info->data + len, "Histogram of sizes (512B secs)n");
  1623. for (i = 0; i < 16; i++) {
  1624. len += sprintf (info->data + len, "%7d ",
  1625.                                 dasd_global_profile.dasd_io_secs[i] >> shift);
  1626. }
  1627. len += sprintf (info->data + len, "n");
  1628. len += sprintf (info->data + len, "Histogram of I/O times (microseconds)n");
  1629. for (i = 0; i < 16; i++) {
  1630. len += sprintf (info->data + len, "%7d ",
  1631.                                 dasd_global_profile.dasd_io_times[i] >> shift);
  1632. }
  1633. len += sprintf (info->data + len, "n");
  1634. for (; i < 32; i++) {
  1635. len += sprintf (info->data + len, "%7d ",
  1636.                                 dasd_global_profile.dasd_io_times[i] >> shift);
  1637. }
  1638. len += sprintf (info->data + len, "n");
  1639. len += sprintf (info->data + len, "Histogram of I/O times per sectorn");
  1640. for (i = 0; i < 16; i++) {
  1641. len += sprintf (info->data + len, "%7d ",
  1642.                                 dasd_global_profile.dasd_io_timps[i] >> shift);
  1643. }
  1644. len += sprintf (info->data + len, "n");
  1645. for (; i < 32; i++) {
  1646. len += sprintf (info->data + len, "%7d ",
  1647.                                 dasd_global_profile.dasd_io_timps[i] >> shift);
  1648. }
  1649. len += sprintf (info->data + len, "n");
  1650. len += sprintf (info->data + len, "Histogram of I/O time till sschn");
  1651. for (i = 0; i < 16; i++) {
  1652. len += sprintf (info->data + len, "%7d ",
  1653.                                 dasd_global_profile.dasd_io_time1[i] >> shift);
  1654. }
  1655. len += sprintf (info->data + len, "n");
  1656. for (; i < 32; i++) {
  1657. len += sprintf (info->data + len, "%7d ",
  1658.                                 dasd_global_profile.dasd_io_time1[i] >> shift);
  1659. }
  1660. len += sprintf (info->data + len, "n");
  1661. len += sprintf (info->data + len,
  1662.                         "Histogram of I/O time between ssch and irqn");
  1663. for (i = 0; i < 16; i++) {
  1664. len += sprintf (info->data + len, "%7d ",
  1665.                                 dasd_global_profile.dasd_io_time2[i] >> shift);
  1666. }
  1667. len += sprintf (info->data + len, "n");
  1668. for (; i < 32; i++) {
  1669. len += sprintf (info->data + len, "%7d ",
  1670.                                 dasd_global_profile.dasd_io_time2[i] >> shift);
  1671. }
  1672. len += sprintf (info->data + len, "n");
  1673. len += sprintf (info->data + len,
  1674.                         "Histogram of I/O time between ssch and irq per sectorn");
  1675. for (i = 0; i < 16; i++) {
  1676. len += sprintf (info->data + len, "%7d ",
  1677.                                 dasd_global_profile.dasd_io_time2ps[i] >> shift);
  1678. }
  1679. len += sprintf (info->data + len, "n");
  1680. for (; i < 32; i++) {
  1681. len += sprintf (info->data + len, "%7d ",
  1682.                                 dasd_global_profile.dasd_io_time2ps[i] >> shift);
  1683. }
  1684. len += sprintf (info->data + len, "n");
  1685. len += sprintf (info->data + len,
  1686.                         "Histogram of I/O time between irq and endn");
  1687. for (i = 0; i < 16; i++) {
  1688. len +=
  1689.     sprintf (info->data + len, "%7d ",
  1690.      dasd_global_profile.dasd_io_time3[i] >> shift);
  1691. }
  1692. len += sprintf (info->data + len, "n");
  1693. for (; i < 32; i++) {
  1694. len += sprintf (info->data + len, "%7d ",
  1695.                                 dasd_global_profile.dasd_io_time3[i] >> shift);
  1696. }
  1697. len += sprintf (info->data + len, "n");
  1698. len += sprintf (info->data + len,
  1699.                         "# of req in chanq at enqueuing (1..32) n");
  1700. for (i = 0; i < 16; i++) {
  1701. len += sprintf (info->data + len, "%7d ",
  1702.                                 dasd_global_profile.dasd_io_nr_req[i] >> shift);
  1703. }
  1704. len += sprintf (info->data + len, "n");
  1705. for (; i < 32; i++) {
  1706. len += sprintf (info->data + len, "%7d ",
  1707.                                 dasd_global_profile.dasd_io_nr_req[i] >> shift);
  1708. }
  1709. len += sprintf (info->data + len, "n");
  1710. info->len = len;
  1711. return rc;
  1712. }
  1713. static ssize_t
  1714. dasd_statistics_write (struct file *file, const char *user_buf,
  1715.        size_t user_len, loff_t * offset)
  1716. {
  1717. char *buffer;
  1718. if(user_len > 65536)
  1719. user_len = 65536;
  1720. buffer = vmalloc (user_len);
  1721. if (buffer == NULL)
  1722. return -ENOMEM;
  1723. if (copy_from_user (buffer, user_buf, user_len)) {
  1724. vfree (buffer);
  1725. return -EFAULT;
  1726. }
  1727. buffer[user_len] = 0;
  1728. printk (KERN_INFO PRINTK_HEADER "/proc/dasd/statictics: '%s'n",
  1729. buffer);
  1730. if (strncmp (buffer, "reset", 4)) {
  1731. memset (&dasd_global_profile, 0, sizeof (dasd_profile_info_t));
  1732. }
  1733. return user_len;
  1734. }
  1735. static struct file_operations dasd_statistics_file_ops = {
  1736. read:dasd_generic_read, /* read */
  1737. open:dasd_statistics_open, /* open */
  1738. write:dasd_statistics_write, /* write */
  1739. release:dasd_devices_close, /* close */
  1740. };
  1741. static struct inode_operations dasd_statistics_inode_ops = {
  1742. };
  1743. int
  1744. dasd_proc_init (void)
  1745. {
  1746. int rc = 0;
  1747. dasd_proc_root_entry = proc_mkdir ("dasd", &proc_root);
  1748. dasd_devices_entry = create_proc_entry ("devices",
  1749. S_IFREG | S_IRUGO | S_IWUSR,
  1750. dasd_proc_root_entry);
  1751. dasd_devices_entry->proc_fops = &dasd_devices_file_ops;
  1752. dasd_devices_entry->proc_iops = &dasd_devices_inode_ops;
  1753. dasd_statistics_entry = create_proc_entry ("statistics",
  1754.    S_IFREG | S_IRUGO | S_IWUSR,
  1755.    dasd_proc_root_entry);
  1756. dasd_statistics_entry->proc_fops = &dasd_statistics_file_ops;
  1757. dasd_statistics_entry->proc_iops = &dasd_statistics_inode_ops;
  1758. return rc;
  1759. }
  1760. void
  1761. dasd_proc_cleanup (void)
  1762. {
  1763. remove_proc_entry ("devices", dasd_proc_root_entry);
  1764. remove_proc_entry ("statistics", dasd_proc_root_entry);
  1765. remove_proc_entry ("dasd", &proc_root);
  1766. }
  1767. int
  1768. dasd_request_module ( void *name ) {
  1769. int rc = -ERESTARTSYS;
  1770.      strcpy(current->comm, name);
  1771.     daemonize();
  1772.     while ( current->fs->root == NULL ) { /* wait for root-FS */
  1773.          DECLARE_WAIT_QUEUE_HEAD(wait);
  1774.          sleep_on_timeout(&wait,HZ); /* wait in steps of one second */
  1775. while ( (rc=request_module(name)) != 0 ) {
  1776.          DECLARE_WAIT_QUEUE_HEAD(wait);
  1777. printk ( KERN_INFO "request_module returned %d for %sn",
  1778.                          rc,
  1779.                          (char*)name);
  1780.          sleep_on_timeout(&wait,5* HZ); /* wait in steps of 5 seconds */
  1781.      }
  1782.      return rc;
  1783. }
  1784. /* SECTION: Initializing the driver */
  1785. int __init
  1786. dasd_init (void)
  1787. {
  1788. int rc = 0;
  1789. int irq;
  1790. major_info_t *major_info = NULL;
  1791. struct list_head *l;
  1792. printk (KERN_INFO PRINTK_HEADER "initializing...n");
  1793. dasd_debug_area = debug_register (DASD_NAME, 0, 2, 5 * sizeof (long));
  1794. debug_register_view (dasd_debug_area, &debug_sprintf_view);
  1795. debug_register_view (dasd_debug_area, &debug_hex_ascii_view);
  1796. init_waitqueue_head (&dasd_init_waitq);
  1797. if (dasd_debug_area == NULL) {
  1798. goto failed;
  1799. }
  1800. DASD_DRIVER_DEBUG_EVENT (0, dasd_init, "%s", 
  1801.                                  "ENTRY");
  1802. dasd_devfs_handle = devfs_mk_dir (NULL, DASD_NAME, NULL);
  1803. if (dasd_devfs_handle < 0) {
  1804. DASD_DRIVER_DEBUG_EVENT (1, dasd_init, "%s", 
  1805.                                          "no devfs");
  1806. goto failed;
  1807. }
  1808. list_for_each (l, &dasd_major_info[0].list) {
  1809. major_info = list_entry (l, major_info_t, list);
  1810. if ((rc = dasd_register_major (major_info)) > 0) {
  1811. DASD_DRIVER_DEBUG_EVENT (1, dasd_init,
  1812.  "major %d: success",
  1813.  major_info->gendisk.major);
  1814. printk (KERN_INFO PRINTK_HEADER
  1815. "Registered successfully to major no %un",
  1816. major_info->gendisk.major);
  1817. } else {
  1818. DASD_DRIVER_DEBUG_EVENT (1, dasd_init,
  1819.  "major %d: failed",
  1820.  major_info->gendisk.major);
  1821. printk (KERN_WARNING PRINTK_HEADER
  1822. "Couldn't register successfully to major no %dn",
  1823. major_info->gendisk.major);
  1824. /* revert registration of major infos */
  1825. goto failed;
  1826. }
  1827. }
  1828. #ifndef MODULE
  1829. dasd_split_parm_string (dasd_parm_string);
  1830. #endif /* ! MODULE */
  1831. rc = dasd_parse (dasd);
  1832. if (rc) {
  1833. DASD_DRIVER_DEBUG_EVENT (1, dasd_init, "%s",
  1834.                                          "invalid range found");
  1835. goto failed;
  1836. }
  1837. rc = dasd_proc_init ();
  1838. if (rc) {
  1839. DASD_DRIVER_DEBUG_EVENT (1, dasd_init, "%s", "no proc-FS");
  1840. goto failed;
  1841. }
  1842. genhd_dasd_name = dasd_device_name;
  1843. genhd_dasd_ioctl = dasd_ioctl;
  1844. if (dasd_autodetect) { /* update device range to all devices */
  1845. for (irq = get_irq_first (); irq != -ENODEV;
  1846.      irq = get_irq_next (irq)) {
  1847. int devno = get_devno_by_irq (irq);
  1848. int index = dasd_devindex_from_devno (devno);
  1849. if (index == -ENODEV) { /* not included in ranges */
  1850. DASD_DRIVER_DEBUG_EVENT (2, dasd_init,
  1851.  "add %04x to range",
  1852.  devno);
  1853. dasd_add_range (devno, devno, DASD_DEFAULT_FEATURES);
  1854. }
  1855. }
  1856. }
  1857. if (MACHINE_IS_VM) {
  1858. #ifdef CONFIG_DASD_DIAG
  1859. rc = dasd_diag_init ();
  1860. if (rc == 0) {
  1861. DASD_DRIVER_DEBUG_EVENT (1, dasd_init,
  1862.  "DIAG discipline %s",
  1863.  "success");
  1864. printk (KERN_INFO PRINTK_HEADER
  1865. "Registered DIAG discipline successfullyn");
  1866. } else {
  1867. DASD_DRIVER_DEBUG_EVENT (1, dasd_init,
  1868.  "DIAG discipline %s",
  1869.  "failed");
  1870. goto failed;
  1871. }
  1872. #endif /* CONFIG_DASD_DIAG */
  1873. #if defined(CONFIG_DASD_DIAG_MODULE) && defined(CONFIG_DASD_AUTO_DIAG)
  1874.                 kernel_thread(dasd_request_module,"dasd_diag_mod",SIGCHLD);
  1875. #endif /* CONFIG_DASD_AUTO_DIAG */
  1876. }
  1877. #ifdef CONFIG_DASD_ECKD
  1878. rc = dasd_eckd_init ();
  1879. if (rc == 0) {
  1880. DASD_DRIVER_DEBUG_EVENT (1, dasd_init,
  1881.  "ECKD discipline %s", "success");
  1882. printk (KERN_INFO PRINTK_HEADER
  1883. "Registered ECKD discipline successfullyn");
  1884. } else {
  1885. DASD_DRIVER_DEBUG_EVENT (1, dasd_init,
  1886.  "ECKD discipline %s", "failed");
  1887. goto failed;
  1888. }
  1889. #endif /* CONFIG_DASD_ECKD */
  1890. #if defined(CONFIG_DASD_ECKD_MODULE) && defined(CONFIG_DASD_AUTO_ECKD)
  1891.         kernel_thread(dasd_request_module,"dasd_eckd_mod",SIGCHLD);
  1892. #endif /* CONFIG_DASD_AUTO_ECKD */
  1893. #ifdef CONFIG_DASD_FBA
  1894. rc = dasd_fba_init ();
  1895. if (rc == 0) {
  1896. DASD_DRIVER_DEBUG_EVENT (1, dasd_init,
  1897.  "FBA discipline %s", "success");
  1898. printk (KERN_INFO PRINTK_HEADER
  1899. "Registered FBA discipline successfullyn");
  1900. } else {
  1901. DASD_DRIVER_DEBUG_EVENT (1, dasd_init,
  1902.  "FBA discipline %s", "failed");
  1903. goto failed;
  1904. }
  1905. #endif /* CONFIG_DASD_FBA */
  1906. #if defined(CONFIG_DASD_FBA_MODULE) && defined(CONFIG_DASD_AUTO_FBA)
  1907.         kernel_thread(dasd_request_module,"dasd_fba_mod",SIGCHLD);
  1908. #endif /* CONFIG_DASD_AUTO_FBA */
  1909.         {
  1910.                 char **disc=dasd_disciplines;
  1911.                 while (*disc) {
  1912.                         kernel_thread(dasd_request_module,*disc,SIGCHLD);
  1913.                         disc++;
  1914.                 }
  1915.         }
  1916. rc = 0;
  1917. goto out;
  1918.       failed:
  1919. printk (KERN_INFO PRINTK_HEADER
  1920. "initialization not performed due to errorsn");
  1921. cleanup_dasd ();
  1922.       out:
  1923. DASD_DRIVER_DEBUG_EVENT (0, dasd_init, "%s", "LEAVE");
  1924. printk (KERN_INFO PRINTK_HEADER "initialization finishedn");
  1925. return rc;
  1926. }
  1927. static void
  1928. cleanup_dasd (void)
  1929. {
  1930. int i,rc=0;
  1931. major_info_t *major_info = NULL;
  1932. struct list_head *l,*n;
  1933. dasd_range_t *range;
  1934. printk (KERN_INFO PRINTK_HEADER "shutting downn");
  1935.         DASD_DRIVER_DEBUG_EVENT(0,"cleanup_dasd","%s","ENTRY");
  1936. dasd_disable_ranges (&dasd_range_head, NULL, 1, 1);
  1937.         if (MACHINE_IS_VM) {
  1938. #ifdef CONFIG_DASD_DIAG
  1939.                 dasd_diag_cleanup ();
  1940.                 DASD_DRIVER_DEBUG_EVENT (1, "cleanup_dasd",
  1941.                                          "DIAG discipline %s", "success");
  1942.                 printk (KERN_INFO PRINTK_HEADER
  1943. "De-Registered DIAG discipline successfullyn");
  1944. #endif /* CONFIG_DASD_ECKD_BUILTIN */
  1945. }
  1946. #ifdef CONFIG_DASD_FBA
  1947. dasd_fba_cleanup ();
  1948. DASD_DRIVER_DEBUG_EVENT (1, "cleanup_dasd",
  1949.  "FBA discipline %s", "success");
  1950. printk (KERN_INFO PRINTK_HEADER
  1951. "De-Registered FBA discipline successfullyn");
  1952. #endif /* CONFIG_DASD_ECKD_BUILTIN */
  1953. #ifdef CONFIG_DASD_ECKD
  1954. dasd_eckd_cleanup ();
  1955. DASD_DRIVER_DEBUG_EVENT (1, "cleanup_dasd",
  1956.  "ECKD discipline %s", "success");
  1957. printk (KERN_INFO PRINTK_HEADER
  1958. "De-Registered ECKD discipline successfullyn");
  1959. #endif /* CONFIG_DASD_ECKD_BUILTIN */
  1960. genhd_dasd_name = NULL;
  1961. genhd_dasd_ioctl = NULL;
  1962. dasd_proc_cleanup ();
  1963.         
  1964. list_for_each_safe (l, n, &dasd_major_info[0].list) {
  1965. major_info = list_entry (l, major_info_t, list);
  1966. for (i = 0; i < DASD_PER_MAJOR; i++) {
  1967. kfree (major_info->dasd_device[i]);
  1968. }
  1969. if ((major_info->flags & DASD_MAJOR_INFO_REGISTERED) &&
  1970.     (rc = dasd_unregister_major (major_info)) == 0) {
  1971. DASD_DRIVER_DEBUG_EVENT (1, "cleanup_dasd",
  1972.  "major %d: success",
  1973.  major_info->gendisk.major);
  1974. printk (KERN_INFO PRINTK_HEADER
  1975. "Unregistered successfully from major no %un",
  1976. major_info->gendisk.major);
  1977. } else {
  1978. DASD_DRIVER_DEBUG_EVENT (1, "cleanup_dasd",
  1979.  "major %d: failed",
  1980.  major_info->gendisk.major);
  1981. printk (KERN_WARNING PRINTK_HEADER
  1982. "Couldn't unregister successfully from major no %d rc = %dn",
  1983. major_info->gendisk.major, rc);
  1984.    }
  1985.    }
  1986. list_for_each_safe (l, n, &dasd_range_head.list) {
  1987. range = list_entry (l, dasd_range_t, list);
  1988.                 dasd_remove_range(range);
  1989.         }
  1990. #ifndef MODULE
  1991.         for( i = 0; i < 256; i++ )
  1992.                 if ( dasd[i] ) {
  1993.                         kfree(dasd[i]);
  1994.                         dasd[i] = NULL;
  1995.                 }
  1996. #endif /* MODULE */
  1997.         if (dasd_devfs_handle) 
  1998.                 devfs_unregister(dasd_devfs_handle);
  1999.         if (dasd_debug_area != NULL )
  2000.                 debug_unregister(dasd_debug_area);
  2001. printk (KERN_INFO PRINTK_HEADER "shutdown completedn");
  2002.         DASD_DRIVER_DEBUG_EVENT(0,"cleanup_dasd","%s","LEAVE");
  2003. }
  2004. #ifdef MODULE
  2005. int
  2006. init_module (void)
  2007. {
  2008. int rc = 0;
  2009. rc = dasd_init ();
  2010. return rc;
  2011. }
  2012. void
  2013. cleanup_module (void)
  2014. {
  2015. cleanup_dasd ();
  2016. return;
  2017. }
  2018. #endif
  2019. /*
  2020.  * Overrides for Emacs so that we follow Linus's tabbing style.
  2021.  * Emacs will notice this stuff at the end of the file and automatically
  2022.  * adjust the settings for this buffer only.  This must remain at the end
  2023.  * of the file.
  2024.  * ---------------------------------------------------------------------------
  2025.  * Local variables:
  2026.  * c-indent-level: 4
  2027.  * c-brace-imaginary-offset: 0
  2028.  * c-brace-offset: -4
  2029.  * c-argdecl-indent: 4
  2030.  * c-label-offset: -4
  2031.  * c-continued-statement-offset: 4
  2032.  * c-continued-brace-offset: 0
  2033.  * indent-tabs-mode: nil
  2034.  * tab-width: 8
  2035.  * End:
  2036.  */