Staging: pata_rdc: convert code to work in 2.6.29
[linux-2.6] / drivers / staging / pata_rdc / pata_rdc.c
1 #include <linux/kernel.h>
2 #include <linux/init.h>
3 #include <linux/module.h>
4
5 #include <linux/pci.h>
6 #include <linux/device.h>
7
8 #include <scsi/scsi_host.h>
9 #include <linux/libata.h>
10
11 #include "pata_rdc.h"
12
13 //#define DBGPRINTF
14
15 #ifdef DBGPRINTF
16
17     #define dbgprintf(format, arg...) printk(KERN_INFO format, ## arg)
18
19 #else
20
21     #define dbgprintf(...)
22
23 #endif
24
25 // Driver Info.
26
27 #define DRIVER_NAME         "pata_rdc"  // sata_rdc for SATA
28 #define DRIVER_VERSION      "2.6.28"    // based on kernel version.
29                                         // because each kernel main version has its libata, we follow kernel to determine the last libata version.
30
31
32 static const struct pci_device_id rdc_pata_id_table[] = {
33     { 0x17F3, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RDC_17F31011},
34     { 0x17F3, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RDC_17F31012},
35     { }    /* terminate list */
36 };
37
38 MODULE_LICENSE("GPL");
39 MODULE_AUTHOR("this version author is RDC");    // replace "RDC" with the last maintainer.
40 MODULE_DESCRIPTION("RDC PCI IDE Driver");
41 MODULE_DEVICE_TABLE(pci, rdc_pata_id_table);
42 MODULE_VERSION(DRIVER_VERSION);
43
44 // a pci driver
45 static struct pci_driver rdc_pata_driver = {
46     .name           = DRIVER_NAME,
47     .id_table       = rdc_pata_id_table,
48     .probe          = rdc_init_one,
49     .remove         = ata_pci_remove_one,
50 #ifdef CONFIG_PM
51     .suspend        = ata_pci_device_suspend,
52     .resume         = ata_pci_device_resume,
53 #endif
54 };
55
56 static unsigned int in_module_init = 1; // hotplugging check???
57 static int __init pata_rdc_init(void)
58 {
59     int rc;
60
61     dbgprintf("pata_rdc_init\n");
62     rc = pci_register_driver(&rdc_pata_driver);
63     if (rc)
64     {
65         dbgprintf("pata_rdc_init faile\n");
66         return rc;
67     }
68
69     in_module_init = 0;
70
71     return 0;
72 }
73
74 static void __exit pata_rdc_exit(void)
75 {
76     dbgprintf("pata_rdc_exit\n");
77     pci_unregister_driver(&rdc_pata_driver);
78 }
79
80 module_init(pata_rdc_init);
81 module_exit(pata_rdc_exit);
82
83 // ata device data
84
85 static struct pci_bits ATA_Decode_Enable_Bits[] = { // see ATA Host Adapters Standards.
86     { 0x41U, 1U, 0x80UL, 0x80UL },    /* port (Channel) 0 */
87     { 0x43U, 1U, 0x80UL, 0x80UL },    /* port (Channel) 1 */
88 };
89
90 static struct scsi_host_template rdc_pata_sht = {    // pata host template
91     ATA_BMDMA_SHT(DRIVER_NAME),
92 };
93
94 static const struct ata_port_operations rdc_pata_ops = {
95     .inherits           = &ata_bmdma_port_ops,
96
97     .port_start         = rdc_pata_port_start,
98     .port_stop          = rdc_pata_port_stop,
99     .prereset           = rdc_pata_prereset,
100     .cable_detect       = rdc_pata_cable_detect,
101     .set_piomode        = rdc_pata_set_piomode,
102     .set_dmamode        = rdc_pata_set_dmamode,
103
104 };
105
106 static struct ata_port_info rdc_pata_port_info[] = {
107     [RDC_17F31011] =
108     {
109         .flags          = ATA_FLAG_SLAVE_POSS,
110         .pio_mask       = 0x1f,    /* pio0-4 */
111         .mwdma_mask     = 0x07, /* mwdma0-2 */
112         .udma_mask      = ATA_UDMA5, /* udma0-5 */
113         .port_ops       = &rdc_pata_ops,
114     },
115
116     [RDC_17F31012] =
117     {
118         .flags          = ATA_FLAG_SLAVE_POSS,
119         .pio_mask       = 0x1f,    /* pio0-4 */
120         .mwdma_mask     = 0x07, /* mwdma0-2 */
121         .udma_mask      = ATA_UDMA5, /* udma0-5 */
122         .port_ops       = &rdc_pata_ops,
123     },
124
125
126 };
127
128
129
130
131 // callback function for pci_driver
132
133 /**
134  *    Register ATA PCI device with kernel services
135  *    @pdev: PCI device to register
136  *    @ent: Entry in sch_pci_tbl matching with @pdev
137  *
138  *    LOCKING:
139  *    Inherited from PCI layer (may sleep).
140  *
141  *    RETURNS:
142  *    Zero on success, or -ERRNO value.
143  */
144 static int __devinit rdc_init_one(
145     struct pci_dev *pdev,
146     const struct pci_device_id *ent
147     )
148 {
149     //struct device *dev = &pdev->dev;
150     struct ata_port_info port_info[2];
151     const struct ata_port_info *ppinfo[] = { &port_info[0], &port_info[1] };
152
153     int rc;
154
155     dbgprintf("rdc_init_one\n");
156
157     /* no hotplugging support (FIXME) */ // why???
158     if (!in_module_init)
159     {
160         dbgprintf("rdc_init_one in_module_init == 0 failed \n");
161         return -ENODEV;
162     }
163     port_info[0] = rdc_pata_port_info[ent->driver_data];
164     port_info[1] = rdc_pata_port_info[ent->driver_data];
165
166     /* enable device and prepare host */
167     rc = pci_enable_device(pdev);
168     if (rc)
169     {
170         dbgprintf("rdc_init_one pci_enable_device failed \n");
171         return rc;
172     }
173     /* initialize controller */
174
175     pci_intx(pdev, 1);  // enable interrupt
176
177     return ata_pci_sff_init_one(pdev, ppinfo, &rdc_pata_sht, NULL);
178 }
179
180 // callback function for ata_port
181
182 /**
183  *    Set port up for dma.
184  *    @ap: Port to initialize
185  *
186  *    Called just after data structures for each port are
187  *    initialized.  Allocates space for PRD table if the device
188  *    is DMA capable SFF.
189
190     Some drivers also use this entry point as a chance to allocate driverprivate
191     memory for ap->private_data.
192
193  *
194  *    May be used as the port_start() entry in ata_port_operations.
195  *
196  *    LOCKING:
197  *    Inherited from caller.
198  */
199 static int rdc_pata_port_start(
200     struct ata_port *ap
201     )
202 {
203     uint    Channel;
204
205     Channel = ap->port_no;
206     dbgprintf("rdc_pata_port_start Channel: %u \n", Channel);
207     if (ap->ioaddr.bmdma_addr)
208     {
209         return ata_port_start(ap);
210     }
211     else
212     {
213         dbgprintf("rdc_pata_port_start return 0 !!!\n");
214         return 0;
215     }
216 }
217
218 static void rdc_pata_port_stop(
219     struct ata_port *ap
220     )
221 {
222     uint    Channel;
223
224     Channel = ap->port_no;
225
226     dbgprintf("rdc_pata_port_stop Channel: %u \n", Channel);
227 }
228
229 /**
230  *    prereset for PATA host controller
231  *    @link: Target link
232  *    @deadline: deadline jiffies for the operation
233  *
234  *    LOCKING:
235  *    None (inherited from caller).
236  */
237 static int rdc_pata_prereset(
238     struct ata_link *link,
239     unsigned long deadline
240     )
241 {
242     struct pci_dev *pdev;
243     struct ata_port *ap;
244
245     uint    Channel;
246
247     dbgprintf("rdc_pata_prereset\n");
248
249     ap = link->ap;
250     pdev = to_pci_dev(ap->host->dev);
251
252     Channel = ap->port_no;
253
254     // test ATA Decode Enable Bits, should be enable.
255     if (!pci_test_config_bits(pdev, &ATA_Decode_Enable_Bits[Channel]))
256     {
257         dbgprintf("rdc_pata_prereset Channel: %u, Decode Disable\n", Channel);
258         return -ENOENT;
259     }
260     else
261     {
262         dbgprintf("rdc_pata_prereset Channel: %u, Decode Enable\n", Channel);
263         return ata_std_prereset(link, deadline);
264     }
265 }
266
267 /**
268  *    Probe host controller cable detect info
269  *    @ap: Port for which cable detect info is desired
270  *
271  *    Read cable indicator from ATA PCI device's PCI config
272  *    register.  This register is normally set by firmware (BIOS).
273  *
274  *    LOCKING:
275  *    None (inherited from caller).
276  */
277
278 static int rdc_pata_cable_detect(
279     struct ata_port *ap
280     )
281 {
282     struct pci_dev *pdev;
283
284     uint    Channel;
285
286     uint    Mask;
287     u32     u32Value;
288
289     dbgprintf("rdc_pata_cable_detect\n");
290
291     pdev = to_pci_dev(ap->host->dev);
292
293     Channel = ap->port_no;
294
295     if (Channel == 0)
296     {
297         Mask = ATAConfiguration_IDEIOConfiguration_PrimaryDeviceCable80Report;
298     }
299     else
300     {
301         Mask = ATAConfiguration_IDEIOConfiguration_SecondaryDeviceCable80Report;
302     }
303
304     /* check BIOS cable detect results */
305     pci_read_config_dword(pdev, ATAConfiguration_ID_IDEIOConfiguration + ATAConfiguration_PCIOffset, &u32Value);
306
307     if ((u32Value & Mask) == 0)
308     {
309         dbgprintf("rdc_pata_cable_detect Channel: %u, PATA40 \n", Channel);
310         return ATA_CBL_PATA40;
311     }
312     else
313     {
314         dbgprintf("rdc_pata_cable_detect Channel: %u, PATA80 \n", Channel);
315         return ATA_CBL_PATA80;
316     }
317 }
318
319 /**
320  *    Initialize host controller PATA PIO timings
321  *    @ap: Port whose timings we are configuring
322  *    @adev: um
323  *
324  *    Set PIO mode for device, in host controller PCI config space.
325  *
326  *    LOCKING:
327  *    None (inherited from caller).
328  */
329
330 static void rdc_pata_set_piomode(
331     struct ata_port *ap,
332     struct ata_device *adev
333     )
334 {
335     struct pci_dev *pdev;
336
337     uint    Channel;
338     uint    DeviceID;
339
340     uint    PIOTimingMode;
341     uint    PrefetchPostingEnable;
342
343     dbgprintf("rdc_pata_set_piomode\n");
344
345     pdev    = to_pci_dev(ap->host->dev);
346
347     Channel = ap->port_no;
348     DeviceID = adev->devno;
349     PIOTimingMode = adev->pio_mode - XFER_PIO_0;  // piomode = 0, 1, 2, 3... ; adev->pio_mode = XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3...
350
351     if (adev->class == ATA_DEV_ATA)
352     {
353         PrefetchPostingEnable = TRUE;
354     }
355     else
356     {   // ATAPI, CD DVD Rom
357         PrefetchPostingEnable = FALSE;
358     }
359
360     /* PIO configuration clears DTE unconditionally.  It will be
361      * programmed in set_dmamode which is guaranteed to be called
362      * after set_piomode if any DMA mode is available.
363      */
364
365      /* Ensure the UDMA bit is off - it will be turned back on if
366        UDMA is selected */
367
368     if (Channel == 0)
369     {
370         ATAHostAdapter_SetPrimaryPIO(
371             pdev,
372             DeviceID,
373             PIOTimingMode,
374             TRUE,//DMAEnable,
375             PrefetchPostingEnable
376             );
377
378         ATAHostAdapter_SetPrimaryUDMA(
379             pdev,
380             DeviceID,
381             FALSE,//UDMAEnable,
382             UDMA0
383             );
384     }
385     else
386     {
387         ATAHostAdapter_SetSecondaryPIO(
388             pdev,
389             DeviceID,
390             PIOTimingMode,
391             TRUE,//DMAEnable,
392             PrefetchPostingEnable
393             );
394
395         ATAHostAdapter_SetSecondaryUDMA(
396             pdev,
397             DeviceID,
398             FALSE,//UDMAEnable,
399             UDMA0
400             );
401     }
402     dbgprintf("rdc_pata_set_piomode Channel: %u, DeviceID: %u, PIO: %d \n", Channel, DeviceID, PIOTimingMode);
403 }
404
405 /**
406  *    Initialize host controller PATA DMA timings
407  *    @ap: Port whose timings we are configuring
408  *    @adev: um
409  *
410  *    Set MW/UDMA mode for device, in host controller PCI config space.
411  *
412  *    LOCKING:
413  *    None (inherited from caller).
414  */
415
416 static void rdc_pata_set_dmamode(
417     struct ata_port *ap,
418     struct ata_device *adev
419     )
420 {
421     struct pci_dev *pdev;
422
423     uint    Channel;
424     uint    DeviceID;
425
426     uint    PIOTimingMode;
427     uint    PrefetchPostingEnable;
428     uint    DMATimingMode;
429     uint    UDMAEnable;
430
431     dbgprintf("rdc_pata_set_dmamode\n");
432
433     pdev    = to_pci_dev(ap->host->dev);
434
435     Channel = ap->port_no;
436     DeviceID = adev->devno;
437     PIOTimingMode = adev->pio_mode - XFER_PIO_0;  // piomode = 0, 1, 2, 3... ; adev->pio_mode = XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3...
438     DMATimingMode = adev->dma_mode; // UDMA or MDMA
439
440     if (adev->class == ATA_DEV_ATA)
441     {
442         PrefetchPostingEnable = TRUE;
443     }
444     else
445     {   // ATAPI, CD DVD Rom
446         PrefetchPostingEnable = FALSE;
447     }
448
449     if (ap->udma_mask == 0)
450     {   // ata_port dont support udma. depend on hardware spec.
451         UDMAEnable = FALSE;
452     }
453     else
454     {
455         UDMAEnable = TRUE;
456     }
457
458     /*if (ap->mdma_mask == 0)
459     {
460     }*/
461
462     if (Channel == 0)
463     {
464         if (DMATimingMode >= XFER_UDMA_0)
465         {   // UDMA
466             ATAHostAdapter_SetPrimaryPIO(
467                 pdev,
468                 DeviceID,
469                 PIOTimingMode,
470                 TRUE,//DMAEnable,
471                 PrefetchPostingEnable
472                 );
473
474             ATAHostAdapter_SetPrimaryUDMA(
475                 pdev,
476                 DeviceID,
477                 UDMAEnable,
478                 DMATimingMode - XFER_UDMA_0
479                 );
480             dbgprintf("rdc_pata_set_dmamode Channel: %u, DeviceID: %u, UDMA: %u \n", Channel, DeviceID, (uint)(DMATimingMode - XFER_UDMA_0));
481         }
482         else
483         {   // MDMA
484             ATAHostAdapter_SetPrimaryPIO(
485                 pdev,
486                 DeviceID,
487                 (DMATimingMode - XFER_MW_DMA_0) + PIO2, // MDMA0 = PIO2
488                 TRUE,//DMAEnable,
489                 PrefetchPostingEnable
490                 );
491
492             ATAHostAdapter_SetPrimaryUDMA(
493                 pdev,
494                 DeviceID,
495                 FALSE,//UDMAEnable,
496                 UDMA0
497                 );
498             dbgprintf("rdc_pata_set_dmamode Channel: %u, DeviceID: %u, MDMA: %u \n", Channel, DeviceID, (uint)(DMATimingMode - XFER_MW_DMA_0));
499         }
500     }
501     else
502     {
503         if (DMATimingMode >= XFER_UDMA_0)
504         {   // UDMA
505             ATAHostAdapter_SetSecondaryPIO(
506                 pdev,
507                 DeviceID,
508                 PIOTimingMode,
509                 TRUE,//DMAEnable,
510                 PrefetchPostingEnable
511                 );
512
513             ATAHostAdapter_SetSecondaryUDMA(
514                 pdev,
515                 DeviceID,
516                 UDMAEnable,
517                 DMATimingMode - XFER_UDMA_0
518                 );
519             dbgprintf("rdc_pata_set_dmamode Channel: %u, DeviceID: %u, UDMA: %u \n", Channel, DeviceID, (uint)(DMATimingMode - XFER_UDMA_0));
520         }
521         else
522         {   // MDMA
523             ATAHostAdapter_SetSecondaryPIO(
524                 pdev,
525                 DeviceID,
526                 (DMATimingMode - XFER_MW_DMA_0) + PIO2, // MDMA0 = PIO2
527                 TRUE,//DMAEnable,
528                 PrefetchPostingEnable
529                 );
530
531             ATAHostAdapter_SetSecondaryUDMA(
532                 pdev,
533                 DeviceID,
534                 FALSE,//UDMAEnable,
535                 UDMA0
536                 );
537             dbgprintf("rdc_pata_set_dmamode Channel: %u, DeviceID: %u, MDMA: %u \n", Channel, DeviceID, (uint)(DMATimingMode - XFER_MW_DMA_0));
538         }
539     }
540 }
541
542 // modified PCIDeviceIO code.
543
544 static uint
545 PCIDeviceIO_ReadPCIConfiguration(
546     struct pci_dev *pdev,
547     uint           Offset,
548     uint           Length,
549     void*          pBuffer
550     )
551 {
552     uint    funcresult;
553
554     unchar* pchar;
555
556     uint   i;
557
558     funcresult = TRUE;
559
560     pchar = pBuffer;
561
562     for (i = 0; i < Length; i++)
563     {
564         pci_read_config_byte(pdev, Offset, pchar);
565         Offset++;
566         pchar++;
567     }
568
569     funcresult = TRUE;
570
571     goto funcexit;
572 funcexit:
573
574     return funcresult;
575 }
576
577 static uint
578 PCIDeviceIO_WritePCIConfiguration(
579     struct pci_dev *pdev,
580     uint           Offset,
581     uint           Length,
582     void*          pBuffer
583     )
584 {
585     uint    funcresult;
586
587     unchar* pchar;
588
589     uint   i;
590
591     funcresult = TRUE;
592
593     pchar = pBuffer;
594
595     for (i = 0; i < Length; i++)
596     {
597         pci_write_config_byte(pdev, Offset, *pchar);
598         Offset++;
599         pchar++;
600     }
601
602     funcresult = TRUE;
603
604     goto funcexit;
605 funcexit:
606
607     return funcresult;
608 }
609
610
611 // modified ATAHostAdapter code.
612
613 static uint
614 ATAHostAdapter_SetPrimaryPIO(
615     struct pci_dev *pdev,
616     uint                DeviceID,
617     uint                PIOTimingMode,
618     uint                DMAEnable,
619     uint                PrefetchPostingEnable
620     )
621 {
622     uint    funcresult;
623
624     uint    result;
625
626     uint    ATATimingRegister;
627     uint    Device1TimingRegister;
628
629     funcresult = TRUE;
630
631     ATATimingRegister = 0;
632     Device1TimingRegister = 0;
633
634     result = PCIDeviceIO_ReadPCIConfiguration(
635         pdev,
636         ATAConfiguration_ID_PrimaryTiming + ATAConfiguration_PCIOffset,
637         ATAConfiguration_ID_PrimaryTiming_Size,
638         &ATATimingRegister
639         );
640     if (result == FALSE)
641     {
642         funcresult = FALSE;
643         goto funcexit;
644     }
645
646     result = PCIDeviceIO_ReadPCIConfiguration(
647         pdev,
648         ATAConfiguration_ID_Device1Timing + ATAConfiguration_PCIOffset,
649         ATAConfiguration_ID_Device1Timing_Size,
650         &Device1TimingRegister
651         );
652     if (result == FALSE)
653     {
654         funcresult = FALSE;
655         goto funcexit;
656     }
657
658     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1TimingRegisterEnable;
659
660     switch(DeviceID)
661     {
662         case 0:
663             {
664                 // mask clear
665                 ATATimingRegister &= ~(ATAConfiguration_PrimaryTiming_Device0FastTimingEnable
666                     | ATAConfiguration_PrimaryTiming_Device0IORDYSampleModeEnable
667                     | ATAConfiguration_PrimaryTiming_Device0PrefetchandPostingEnable
668                     | ATAConfiguration_PrimaryTiming_Device0DMATimingEnable
669                     | ATAConfiguration_PrimaryTiming_Device0RecoveryMode
670                     | ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode
671                     );
672
673                 if (PIOTimingMode > PIO0)
674                 {
675                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0FastTimingEnable;
676                 }
677
678                 if (PIOTimingMode >= PIO3)
679                 {
680                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleModeEnable;
681                 }
682
683                 if (PIOTimingMode >= PIO2 && PrefetchPostingEnable == TRUE)
684                 {
685                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0PrefetchandPostingEnable;
686                 }
687
688                 if (DMAEnable == TRUE
689                     && PIOTimingMode >= PIO2)
690                 {
691                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0DMATimingEnable;
692                 }
693
694                 if (PIOTimingMode <= PIO2)
695                 {
696                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0RecoveryMode_0;
697                 }
698                 else if (PIOTimingMode == PIO3)
699                 {
700                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0RecoveryMode_1;
701                 }
702                 else if (PIOTimingMode == PIO4)
703                 {
704                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0RecoveryMode_3;
705                 }
706
707                 if (PIOTimingMode <= PIO1)
708                 {
709                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_0;
710                 }
711                 else if (PIOTimingMode == PIO2)
712                 {
713                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_1;
714                 }
715                 else if (PIOTimingMode <= PIO4)
716                 {
717                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_2;
718                 }
719             }
720             break;
721         case 1:
722             {
723                 ATATimingRegister &= ~(ATAConfiguration_PrimaryTiming_Device1FastTimingEnable
724                     | ATAConfiguration_PrimaryTiming_Device1IORDYSampleModeEnable
725                     | ATAConfiguration_PrimaryTiming_Device1PrefetchandPostingEnable
726                     | ATAConfiguration_PrimaryTiming_Device1DMATimingEnable
727                     );
728
729                 if (PIOTimingMode > PIO0)
730                 {
731                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1FastTimingEnable;
732                 }
733
734                 if (PIOTimingMode >= PIO3)
735                 {
736                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1IORDYSampleModeEnable;
737                 }
738
739                 if (PIOTimingMode >= PIO2 && PrefetchPostingEnable == TRUE)
740                 {
741                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1PrefetchandPostingEnable;
742                 }
743
744                 if (DMAEnable == TRUE
745                     && PIOTimingMode >= PIO2)
746                 {
747                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1DMATimingEnable;
748                 }
749
750                 Device1TimingRegister &= ~(ATAConfiguration_Device1Timing_PrimaryRecoveryMode | ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode);
751
752                 if (PIOTimingMode <= PIO2)
753                 {
754                     Device1TimingRegister |= ATAConfiguration_Device1Timing_PrimaryRecoveryMode_0;
755                 }
756                 else if (PIOTimingMode == PIO3)
757                 {
758                     Device1TimingRegister |= ATAConfiguration_Device1Timing_PrimaryRecoveryMode_1;
759                 }
760                 else if (PIOTimingMode == PIO4)
761                 {
762                     Device1TimingRegister |= ATAConfiguration_Device1Timing_PrimaryRecoveryMode_3;
763                 }
764
765                 if (PIOTimingMode <= PIO1)
766                 {
767                     Device1TimingRegister |= ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode_0;
768                 }
769                 else if (PIOTimingMode == PIO2)
770                 {
771                     Device1TimingRegister |= ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode_1;
772                 }
773                 else if (PIOTimingMode <= PIO4)
774                 {
775                     Device1TimingRegister |= ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode_2;
776                 }
777             }
778             break;
779         default:
780             {
781                 funcresult = FALSE;
782                 goto funcexit;
783             }
784             break;
785     }
786
787     result = PCIDeviceIO_WritePCIConfiguration(
788         pdev,
789         ATAConfiguration_ID_PrimaryTiming + ATAConfiguration_PCIOffset,
790         ATAConfiguration_ID_PrimaryTiming_Size,
791         &ATATimingRegister
792         );
793     if (result == FALSE)
794     {
795         funcresult = FALSE;
796         goto funcexit;
797     }
798
799     result = PCIDeviceIO_WritePCIConfiguration(
800         pdev,
801         ATAConfiguration_ID_Device1Timing + ATAConfiguration_PCIOffset,
802         ATAConfiguration_ID_Device1Timing_Size,
803         &Device1TimingRegister
804         );
805     if (result == FALSE)
806     {
807         funcresult = FALSE;
808         goto funcexit;
809     }
810
811     goto funcexit;
812 funcexit:
813
814     return funcresult;
815 }
816
817 static uint
818 ATAHostAdapter_SetSecondaryPIO(
819     struct pci_dev *pdev,
820     uint                DeviceID,
821     uint                PIOTimingMode,
822     uint                DMAEnable,
823     uint                PrefetchPostingEnable
824     )
825 {
826     uint    funcresult;
827
828     uint    result;
829
830     uint    ATATimingRegister;
831     uint    Device1TimingRegister;
832
833     funcresult = TRUE;
834
835     ATATimingRegister = 0;
836     Device1TimingRegister = 0;
837
838     result = PCIDeviceIO_ReadPCIConfiguration(
839         pdev,
840         ATAConfiguration_ID_SecondaryTiming + ATAConfiguration_PCIOffset,
841         ATAConfiguration_ID_SecondaryTiming_Size,
842         &ATATimingRegister
843         );
844     if (result == FALSE)
845     {
846         funcresult = FALSE;
847         goto funcexit;
848     }
849
850     result = PCIDeviceIO_ReadPCIConfiguration(
851         pdev,
852         ATAConfiguration_ID_Device1Timing + ATAConfiguration_PCIOffset,
853         ATAConfiguration_ID_Device1Timing_Size,
854         &Device1TimingRegister
855         );
856     if (result == FALSE)
857     {
858         funcresult = FALSE;
859         goto funcexit;
860     }
861
862     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1TimingRegisterEnable;
863
864     switch(DeviceID)
865     {
866         case 0:
867             {
868                 // mask clear
869                 ATATimingRegister &= ~(ATAConfiguration_PrimaryTiming_Device0FastTimingEnable
870                     | ATAConfiguration_PrimaryTiming_Device0IORDYSampleModeEnable
871                     | ATAConfiguration_PrimaryTiming_Device0PrefetchandPostingEnable
872                     | ATAConfiguration_PrimaryTiming_Device0DMATimingEnable
873                     | ATAConfiguration_PrimaryTiming_Device0RecoveryMode
874                     | ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode
875                     );
876
877                 if (PIOTimingMode > PIO0)
878                 {
879                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0FastTimingEnable;
880                 }
881
882                 if (PIOTimingMode >= PIO3)
883                 {
884                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleModeEnable;
885                 }
886
887                 if (PIOTimingMode >= PIO2 && PrefetchPostingEnable == TRUE)
888                 {
889                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0PrefetchandPostingEnable;
890                 }
891
892                 if (DMAEnable == TRUE
893                     && PIOTimingMode >= PIO2)
894                 {
895                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0DMATimingEnable;
896                 }
897
898                 if (PIOTimingMode <= PIO2)
899                 {
900                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0RecoveryMode_0;
901                 }
902                 else if (PIOTimingMode == PIO3)
903                 {
904                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0RecoveryMode_1;
905                 }
906                 else if (PIOTimingMode == PIO4)
907                 {
908                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0RecoveryMode_3;
909                 }
910
911                 if (PIOTimingMode <= PIO1)
912                 {
913                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_0;
914                 }
915                 else if (PIOTimingMode == PIO2)
916                 {
917                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_1;
918                 }
919                 else if (PIOTimingMode <= PIO4)
920                 {
921                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_2;
922                 }
923             }
924             break;
925         case 1:
926             {
927                 ATATimingRegister &= ~(ATAConfiguration_PrimaryTiming_Device1FastTimingEnable
928                     | ATAConfiguration_PrimaryTiming_Device1IORDYSampleModeEnable
929                     | ATAConfiguration_PrimaryTiming_Device1PrefetchandPostingEnable
930                     | ATAConfiguration_PrimaryTiming_Device1DMATimingEnable
931                     );
932
933                 if (PIOTimingMode > PIO0)
934                 {
935                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1FastTimingEnable;
936                 }
937
938                 if (PIOTimingMode >= PIO3)
939                 {
940                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1IORDYSampleModeEnable;
941                 }
942
943                 if (PIOTimingMode >= PIO2 && PrefetchPostingEnable == TRUE)
944                 {
945                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1PrefetchandPostingEnable;
946                 }
947
948                 if (DMAEnable == TRUE
949                     && PIOTimingMode >= PIO2)
950                 {
951                     ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1DMATimingEnable;
952                 }
953
954                 Device1TimingRegister &= ~(ATAConfiguration_Device1Timing_SecondaryRecoveryMode | ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode);
955
956                 if (PIOTimingMode <= PIO2)
957                 {
958                     Device1TimingRegister |= ATAConfiguration_Device1Timing_SecondaryRecoveryMode_0;
959                 }
960                 else if (PIOTimingMode == PIO3)
961                 {
962                     Device1TimingRegister |= ATAConfiguration_Device1Timing_SecondaryRecoveryMode_1;
963                 }
964                 else if (PIOTimingMode == PIO4)
965                 {
966                     Device1TimingRegister |= ATAConfiguration_Device1Timing_SecondaryRecoveryMode_3;
967                 }
968
969                 if (PIOTimingMode <= PIO1)
970                 {
971                     Device1TimingRegister |= ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode_0;
972                 }
973                 else if (PIOTimingMode == PIO2)
974                 {
975                     Device1TimingRegister |= ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode_1;
976                 }
977                 else if (PIOTimingMode <= PIO4)
978                 {
979                     Device1TimingRegister |= ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode_2;
980                 }
981             }
982             break;
983         default:
984             {
985                 funcresult = FALSE;
986                 goto funcexit;
987             }
988             break;
989     }
990
991     result = PCIDeviceIO_WritePCIConfiguration(
992         pdev,
993         ATAConfiguration_ID_SecondaryTiming + ATAConfiguration_PCIOffset,
994         ATAConfiguration_ID_SecondaryTiming_Size,
995         &ATATimingRegister
996         );
997     if (result == FALSE)
998     {
999         funcresult = FALSE;
1000         goto funcexit;
1001     }
1002
1003     result = PCIDeviceIO_WritePCIConfiguration(
1004         pdev,
1005         ATAConfiguration_ID_Device1Timing + ATAConfiguration_PCIOffset,
1006         ATAConfiguration_ID_Device1Timing_Size,
1007         &Device1TimingRegister
1008         );
1009     if (result == FALSE)
1010     {
1011         funcresult = FALSE;
1012         goto funcexit;
1013     }
1014
1015     goto funcexit;
1016 funcexit:
1017
1018     return funcresult;
1019 }
1020
1021 static uint
1022 ATAHostAdapter_SetPrimaryUDMA(
1023     struct pci_dev *pdev,
1024     uint                DeviceID,
1025     uint                UDMAEnable,
1026     uint                UDMATimingMode
1027     )
1028 {
1029     uint    funcresult;
1030
1031     uint    result;
1032
1033     uint    UDMAControlRegister;
1034     uint    UDMATimingRegister;
1035     ulong   IDEIOConfigurationRegister;
1036
1037     funcresult = TRUE;
1038
1039     UDMAControlRegister = 0;
1040     UDMATimingRegister = 0;
1041     IDEIOConfigurationRegister = 0;
1042
1043     result = PCIDeviceIO_ReadPCIConfiguration(
1044         pdev,
1045         ATAConfiguration_ID_UDMAControl + ATAConfiguration_PCIOffset,
1046         ATAConfiguration_ID_UDMAControl_Size,
1047         &UDMAControlRegister
1048         );
1049     if (result == FALSE)
1050     {
1051         funcresult = FALSE;
1052         goto funcexit;
1053     }
1054
1055     result = PCIDeviceIO_ReadPCIConfiguration(
1056         pdev,
1057         ATAConfiguration_ID_UDMATiming + ATAConfiguration_PCIOffset,
1058         ATAConfiguration_ID_UDMATiming_Size,
1059         &UDMATimingRegister
1060         );
1061     if (result == FALSE)
1062     {
1063         funcresult = FALSE;
1064         goto funcexit;
1065     }
1066
1067     result = PCIDeviceIO_ReadPCIConfiguration(
1068         pdev,
1069         ATAConfiguration_ID_IDEIOConfiguration + ATAConfiguration_PCIOffset,
1070         ATAConfiguration_ID_IDEIOConfiguration_Size,
1071         &IDEIOConfigurationRegister
1072         );
1073     if (result == FALSE)
1074     {
1075         funcresult = FALSE;
1076         goto funcexit;
1077     }
1078
1079     //Rom Code will determine the device cable type and ATA 100.
1080     //IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_DeviceCable80Report;
1081     //IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_ATA100IsSupported;
1082
1083     switch(DeviceID)
1084     {
1085         case 0:
1086             {
1087                 UDMAControlRegister &= ~(ATAConfiguration_UDMAControl_PrimaryDevice0UDMAModeEnable);
1088                 if (UDMAEnable == TRUE)
1089                 {
1090                     UDMAControlRegister |= ATAConfiguration_UDMAControl_PrimaryDevice0UDMAModeEnable;
1091                 }
1092
1093                 IDEIOConfigurationRegister &= ~(ATAConfiguration_IDEIOConfiguration_PrimaryDevice066MhzEnable
1094                     | ATAConfiguration_IDEIOConfiguration_PrimaryDevice0100MhzEnable
1095                     );
1096
1097                 if (UDMATimingMode >= UDMA5)
1098                 {
1099                     IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_PrimaryDevice0100MhzEnable;
1100                 }
1101                 else if (UDMATimingMode >= UDMA3)
1102                 {
1103                     IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_PrimaryDevice066MhzEnable;
1104                 }
1105
1106                 // if 80 cable report
1107
1108                 UDMATimingRegister &= ~(ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime);
1109
1110                 if (UDMATimingMode == UDMA0)
1111                 {
1112                     UDMATimingRegister |= ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime_0;
1113                 }
1114                 else if (UDMATimingMode == UDMA1 || UDMATimingMode == UDMA3 || UDMATimingMode == UDMA5)
1115                 {
1116                     UDMATimingRegister |= ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime_1;
1117                 }
1118                 else if (UDMATimingMode == UDMA2 || UDMATimingMode == UDMA4)
1119                 {
1120                     UDMATimingRegister |= ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime_2;
1121                 }
1122             }
1123             break;
1124         case 1:
1125             {
1126                 UDMAControlRegister &= ~(ATAConfiguration_UDMAControl_PrimaryDevice1UDMAModeEnable);
1127                 if (UDMAEnable == TRUE)
1128                 {
1129                     UDMAControlRegister |= ATAConfiguration_UDMAControl_PrimaryDevice1UDMAModeEnable;
1130                 }
1131
1132                 IDEIOConfigurationRegister &= ~(ATAConfiguration_IDEIOConfiguration_PrimaryDevice166MhzEnable
1133                     | ATAConfiguration_IDEIOConfiguration_PrimaryDevice1100MhzEnable
1134                     );
1135
1136                 if (UDMATimingMode >= UDMA5)
1137                 {
1138                     IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_PrimaryDevice1100MhzEnable;
1139                 }
1140                 else if (UDMATimingMode >= UDMA3)
1141                 {
1142                     IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_PrimaryDevice166MhzEnable;
1143                 }
1144
1145                 // if 80 cable report
1146
1147                 UDMATimingRegister &= ~(ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime);
1148
1149                 if (UDMATimingMode == UDMA0)
1150                 {
1151                     UDMATimingRegister |= ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime_0;
1152                 }
1153                 else if (UDMATimingMode == UDMA1 || UDMATimingMode == UDMA3 || UDMATimingMode == UDMA5)
1154                 {
1155                     UDMATimingRegister |= ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime_1;
1156                 }
1157                 else if (UDMATimingMode == UDMA2 || UDMATimingMode == UDMA4)
1158                 {
1159                     UDMATimingRegister |= ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime_2;
1160                 }
1161             }
1162             break;
1163         default:
1164             {
1165                 funcresult = FALSE;
1166                 goto funcexit;
1167             }
1168             break;
1169     }
1170
1171     result = PCIDeviceIO_WritePCIConfiguration(
1172         pdev,
1173         ATAConfiguration_ID_UDMAControl + ATAConfiguration_PCIOffset,
1174         ATAConfiguration_ID_UDMAControl_Size,
1175         &UDMAControlRegister
1176         );
1177     if (result == FALSE)
1178     {
1179         funcresult = FALSE;
1180         goto funcexit;
1181     }
1182
1183     result = PCIDeviceIO_WritePCIConfiguration(
1184         pdev,
1185         ATAConfiguration_ID_UDMATiming + ATAConfiguration_PCIOffset,
1186         ATAConfiguration_ID_UDMATiming_Size,
1187         &UDMATimingRegister
1188         );
1189     if (result == FALSE)
1190     {
1191         funcresult = FALSE;
1192         goto funcexit;
1193     }
1194
1195     result = PCIDeviceIO_WritePCIConfiguration(
1196         pdev,
1197         ATAConfiguration_ID_IDEIOConfiguration + ATAConfiguration_PCIOffset,
1198         ATAConfiguration_ID_IDEIOConfiguration_Size,
1199         &IDEIOConfigurationRegister
1200         );
1201     if (result == FALSE)
1202     {
1203         funcresult = FALSE;
1204         goto funcexit;
1205     }
1206
1207     goto funcexit;
1208 funcexit:
1209
1210     return funcresult;
1211 }
1212
1213 static uint
1214 ATAHostAdapter_SetSecondaryUDMA(
1215     struct pci_dev *pdev,
1216     uint                DeviceID,
1217     uint                UDMAEnable,
1218     uint                UDMATimingMode
1219     )
1220 {
1221     uint    funcresult;
1222
1223     uint    result;
1224
1225     uint    UDMAControlRegister;
1226     uint    UDMATimingRegister;
1227     ulong   IDEIOConfigurationRegister;
1228
1229     funcresult = TRUE;
1230
1231     UDMAControlRegister = 0;
1232     UDMATimingRegister = 0;
1233     IDEIOConfigurationRegister = 0;
1234
1235     result = PCIDeviceIO_ReadPCIConfiguration(
1236         pdev,
1237         ATAConfiguration_ID_UDMAControl + ATAConfiguration_PCIOffset,
1238         ATAConfiguration_ID_UDMAControl_Size,
1239         &UDMAControlRegister
1240         );
1241     if (result == FALSE)
1242     {
1243         funcresult = FALSE;
1244         goto funcexit;
1245     }
1246
1247     result = PCIDeviceIO_ReadPCIConfiguration(
1248         pdev,
1249         ATAConfiguration_ID_UDMATiming + ATAConfiguration_PCIOffset,
1250         ATAConfiguration_ID_UDMATiming_Size,
1251         &UDMATimingRegister
1252         );
1253     if (result == FALSE)
1254     {
1255         funcresult = FALSE;
1256         goto funcexit;
1257     }
1258
1259     result = PCIDeviceIO_ReadPCIConfiguration(
1260         pdev,
1261         ATAConfiguration_ID_IDEIOConfiguration + ATAConfiguration_PCIOffset,
1262         ATAConfiguration_ID_IDEIOConfiguration_Size,
1263         &IDEIOConfigurationRegister
1264         );
1265     if (result == FALSE)
1266     {
1267         funcresult = FALSE;
1268         goto funcexit;
1269     }
1270
1271     //Rom Code will determine the device cable type and ATA 100.
1272     //IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_DeviceCable80Report;
1273     //IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_ATA100IsSupported;
1274
1275     switch(DeviceID)
1276     {
1277         case 0:
1278             {
1279                 UDMAControlRegister &= ~(ATAConfiguration_UDMAControl_SecondaryDevice0UDMAModeEnable);
1280                 if (UDMAEnable == TRUE)
1281                 {
1282                     UDMAControlRegister |= ATAConfiguration_UDMAControl_SecondaryDevice0UDMAModeEnable;
1283                 }
1284
1285                 IDEIOConfigurationRegister &= ~(ATAConfiguration_IDEIOConfiguration_SecondaryDevice066MhzEnable
1286                     | ATAConfiguration_IDEIOConfiguration_SecondaryDevice0100MhzEnable
1287                     );
1288
1289                 if (UDMATimingMode >= UDMA5)
1290                 {
1291                     IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_SecondaryDevice0100MhzEnable;
1292                 }
1293                 else if (UDMATimingMode >= UDMA3)
1294                 {
1295                     IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_SecondaryDevice066MhzEnable;
1296                 }
1297
1298                 // if 80 cable report
1299
1300                 UDMATimingRegister &= ~(ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime);
1301
1302                 if (UDMATimingMode == UDMA0)
1303                 {
1304                     UDMATimingRegister |= ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime_0;
1305                 }
1306                 else if (UDMATimingMode == UDMA1 || UDMATimingMode == UDMA3 || UDMATimingMode == UDMA5)
1307                 {
1308                     UDMATimingRegister |= ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime_1;
1309                 }
1310                 else if (UDMATimingMode == UDMA2 || UDMATimingMode == UDMA4)
1311                 {
1312                     UDMATimingRegister |= ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime_2;
1313                 }
1314             }
1315             break;
1316         case 1:
1317             {
1318                 UDMAControlRegister &= ~(ATAConfiguration_UDMAControl_SecondaryDevice1UDMAModeEnable);
1319                 if (UDMAEnable == TRUE)
1320                 {
1321                     UDMAControlRegister |= ATAConfiguration_UDMAControl_SecondaryDevice1UDMAModeEnable;
1322                 }
1323
1324                 IDEIOConfigurationRegister &= ~(ATAConfiguration_IDEIOConfiguration_SecondaryDevice166MhzEnable
1325                     | ATAConfiguration_IDEIOConfiguration_SecondaryDevice1100MhzEnable
1326                     );
1327
1328                 if (UDMATimingMode >= UDMA5)
1329                 {
1330                     IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_SecondaryDevice1100MhzEnable;
1331                 }
1332                 else if (UDMATimingMode >= UDMA3)
1333                 {
1334                     IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_SecondaryDevice166MhzEnable;
1335                 }
1336
1337                 // if 80 cable report
1338
1339                 UDMATimingRegister &= ~(ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime);
1340
1341                 if (UDMATimingMode == UDMA0)
1342                 {
1343                     UDMATimingRegister |= ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime_0;
1344                 }
1345                 else if (UDMATimingMode == UDMA1 || UDMATimingMode == UDMA3 || UDMATimingMode == UDMA5)
1346                 {
1347                     UDMATimingRegister |= ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime_1;
1348                 }
1349                 else if (UDMATimingMode == UDMA2 || UDMATimingMode == UDMA4)
1350                 {
1351                     UDMATimingRegister |= ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime_2;
1352                 }
1353             }
1354             break;
1355         default:
1356             {
1357                 funcresult = FALSE;
1358                 goto funcexit;
1359             }
1360             break;
1361     }
1362
1363     result = PCIDeviceIO_WritePCIConfiguration(
1364         pdev,
1365         ATAConfiguration_ID_UDMAControl + ATAConfiguration_PCIOffset,
1366         ATAConfiguration_ID_UDMAControl_Size,
1367         &UDMAControlRegister
1368         );
1369     if (result == FALSE)
1370     {
1371         funcresult = FALSE;
1372         goto funcexit;
1373     }
1374
1375     result = PCIDeviceIO_WritePCIConfiguration(
1376         pdev,
1377         ATAConfiguration_ID_UDMATiming + ATAConfiguration_PCIOffset,
1378         ATAConfiguration_ID_UDMATiming_Size,
1379         &UDMATimingRegister
1380         );
1381     if (result == FALSE)
1382     {
1383         funcresult = FALSE;
1384         goto funcexit;
1385     }
1386
1387     result = PCIDeviceIO_WritePCIConfiguration(
1388         pdev,
1389         ATAConfiguration_ID_IDEIOConfiguration + ATAConfiguration_PCIOffset,
1390         ATAConfiguration_ID_IDEIOConfiguration_Size,
1391         &IDEIOConfigurationRegister
1392         );
1393     if (result == FALSE)
1394     {
1395         funcresult = FALSE;
1396         goto funcexit;
1397     }
1398
1399     goto funcexit;
1400 funcexit:
1401
1402     return funcresult;
1403 }